diff options
-rw-r--r-- | lauxlib.c | 5 | ||||
-rw-r--r-- | lgc.c | 11 | ||||
-rw-r--r-- | lgc.h | 44 | ||||
-rw-r--r-- | lstate.c | 5 | ||||
-rw-r--r-- | ltests.c | 10 |
5 files changed, 59 insertions, 16 deletions
@@ -1139,12 +1139,11 @@ static unsigned int luai_makeseed (void) { | |||
1139 | unsigned int res; | 1139 | unsigned int res; |
1140 | unsigned int i; | 1140 | unsigned int i; |
1141 | time_t t = time(NULL); | 1141 | time_t t = time(NULL); |
1142 | void *h = buff; | ||
1143 | char *b = (char*)buff; | 1142 | char *b = (char*)buff; |
1144 | addbuff(b, h); /* local variable's address */ | 1143 | addbuff(b, b); /* local variable's address */ |
1145 | addbuff(b, t); /* time */ | 1144 | addbuff(b, t); /* time */ |
1146 | /* fill (rare but possible) remain of the buffer with zeros */ | 1145 | /* fill (rare but possible) remain of the buffer with zeros */ |
1147 | memset(b, 0, BUFSEED * sizeof(int) - BUFSEEDB); | 1146 | memset(b, 0, sizeof(buff) - BUFSEEDB); |
1148 | res = buff[0]; | 1147 | res = buff[0]; |
1149 | for (i = 0; i < BUFSEED; i++) | 1148 | for (i = 0; i < BUFSEED; i++) |
1150 | res ^= (res >> 3) + (res << 7) + buff[i]; | 1149 | res ^= (res >> 3) + (res << 7) + buff[i]; |
@@ -1121,6 +1121,7 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, | |||
1121 | curr->marked = cast_byte(marked | G_SURVIVAL | white); | 1121 | curr->marked = cast_byte(marked | G_SURVIVAL | white); |
1122 | } | 1122 | } |
1123 | else { /* all other objects will be old, and so keep their color */ | 1123 | else { /* all other objects will be old, and so keep their color */ |
1124 | lua_assert(getage(curr) != G_OLD1); /* advanced in 'markold' */ | ||
1124 | setage(curr, nextage[getage(curr)]); | 1125 | setage(curr, nextage[getage(curr)]); |
1125 | if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) | 1126 | if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) |
1126 | *pfirstold1 = curr; /* first OLD1 object in the list */ | 1127 | *pfirstold1 = curr; /* first OLD1 object in the list */ |
@@ -1145,13 +1146,15 @@ static void whitelist (global_State *g, GCObject *p) { | |||
1145 | 1146 | ||
1146 | 1147 | ||
1147 | /* | 1148 | /* |
1148 | ** Correct a list of gray objects. Return pointer to where rest of the | 1149 | ** Correct a list of gray objects. Return a pointer to the last element |
1149 | ** list should be linked. | 1150 | ** left on the list, so that we can link another list to the end of |
1151 | ** this one. | ||
1150 | ** Because this correction is done after sweeping, young objects might | 1152 | ** Because this correction is done after sweeping, young objects might |
1151 | ** be turned white and still be in the list. They are only removed. | 1153 | ** be turned white and still be in the list. They are only removed. |
1152 | ** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list; | 1154 | ** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list; |
1153 | ** Non-white threads also remain on the list; 'TOUCHED2' objects become | 1155 | ** Non-white threads also remain on the list. 'TOUCHED2' objects and |
1154 | ** regular old; they and anything else are removed from the list. | 1156 | ** anything else become regular old, are marked black, and are removed |
1157 | ** from the list. | ||
1155 | */ | 1158 | */ |
1156 | static GCObject **correctgraylist (GCObject **p) { | 1159 | static GCObject **correctgraylist (GCObject **p) { |
1157 | GCObject *curr; | 1160 | GCObject *curr; |
@@ -123,6 +123,43 @@ | |||
123 | #define changeage(o,f,t) \ | 123 | #define changeage(o,f,t) \ |
124 | check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t))) | 124 | check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t))) |
125 | 125 | ||
126 | /* | ||
127 | ** In generational mode, objects are created 'new'. After surviving one | ||
128 | ** cycle, they become 'survival'. Both 'new' and 'survival' can point | ||
129 | ** to any other object, as they are traversed at the end of the cycle. | ||
130 | ** We call them both 'young' objects. | ||
131 | ** If a survival object survives another cycle, it becomes 'old1'. | ||
132 | ** 'old1' objects can still point to survival objects (but not to | ||
133 | ** new objects), so they still must be traversed. After another cycle | ||
134 | ** (that, being old, 'old1' objects will "survive" no matter what) | ||
135 | ** finally the 'old1' object becomes really 'old', and then they | ||
136 | ** are no more traversed. | ||
137 | ** | ||
138 | ** To keep its invariants, the generational mode uses the same barriers | ||
139 | ** also used by the incremental mode. If a young object is caught in a | ||
140 | ** foward barrier, it cannot become old immediately, because it can | ||
141 | ** still point to other young objects. Instead, it becomes 'old0', | ||
142 | ** which in the next cycle becomes 'old1'. So, 'old0' objects is | ||
143 | ** old but can point to new and survival objects; 'old1' is old | ||
144 | ** but cannot point to new objects; and 'old' cannot point to any | ||
145 | ** young object. | ||
146 | ** | ||
147 | ** If any old object ('old0', 'old1', 'old') is caught in a back | ||
148 | ** barrier, it becomes 'touched1' and goes into a gray list, to be | ||
149 | ** visited at the end of the cycle. There it evolves to 'touched2', | ||
150 | ** which can point to survivals but not to new objects. In yet another | ||
151 | ** cycle then it becomes 'old' again. | ||
152 | ** | ||
153 | ** The generational mode must also control the colors of objects, | ||
154 | ** because of the barriers. While the mutator is running, young objects | ||
155 | ** are kept white. 'old', 'old1', and 'touched2' objects are kept black, | ||
156 | ** as they cannot point to new objects; exceptions are threads and open | ||
157 | ** upvalues, which age to 'old1' and 'old' but are kept gray. 'old0' | ||
158 | ** objects may be gray or black, as in the incremental mode. 'touched1' | ||
159 | ** objects are kept gray, as they must be visited again at the end of | ||
160 | ** the cycle. | ||
161 | */ | ||
162 | |||
126 | 163 | ||
127 | /* Default Values for GC parameters */ | 164 | /* Default Values for GC parameters */ |
128 | 165 | ||
@@ -161,9 +198,10 @@ | |||
161 | ** (value * original parameter / 100). | 198 | ** (value * original parameter / 100). |
162 | ** | 199 | ** |
163 | ** For most parameters, which are typically larger than 100%, 2^n is | 200 | ** For most parameters, which are typically larger than 100%, 2^n is |
164 | ** 16 (2^4), allowing maximum values up to 1599. For the minor | 201 | ** 16 (2^4), allowing maximum values up to ~1500%, with a granularity |
165 | ** multiplier, which is typically smaller, 2^n is 64 (2^6) to allow more | 202 | ** of ~6%. For the minor multiplier, which is typically smaller, |
166 | ** precision. | 203 | ** 2^n is 64 (2^6) to allow more precision. In that case, the maximum |
204 | ** value is ~400%, with a granularity of ~1.5%. | ||
167 | */ | 205 | */ |
168 | #define gcparamshift(p) \ | 206 | #define gcparamshift(p) \ |
169 | (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4) | 207 | (offsetof(global_State, p) == offsetof(global_State, genminormul) ? 6 : 4) |
@@ -52,8 +52,9 @@ typedef struct LG { | |||
52 | 52 | ||
53 | 53 | ||
54 | /* | 54 | /* |
55 | ** set GCdebt to a new value keeping the value (totalobjs + GCdebt) | 55 | ** set GCdebt to a new value keeping the real number of allocated |
56 | ** invariant (and avoiding underflows in 'totalobjs') | 56 | ** objects (totalobjs - GCdebt) invariant and avoiding overflows in |
57 | ** 'totalobjs'. | ||
57 | */ | 58 | */ |
58 | void luaE_setdebt (global_State *g, l_obj debt) { | 59 | void luaE_setdebt (global_State *g, l_obj debt) { |
59 | l_obj tb = gettotalobjs(g); | 60 | l_obj tb = gettotalobjs(g); |
@@ -302,8 +302,8 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { | |||
302 | else { /* generational mode */ | 302 | else { /* generational mode */ |
303 | if ((getage(f) == G_OLD && isblack(f)) && !isold(t)) | 303 | if ((getage(f) == G_OLD && isblack(f)) && !isold(t)) |
304 | return 0; | 304 | return 0; |
305 | if (((getage(f) == G_OLD1 || getage(f) == G_TOUCHED2) && isblack(f)) && | 305 | if ((getage(f) == G_OLD1 || getage(f) == G_TOUCHED2) && |
306 | getage(t) == G_NEW) | 306 | getage(t) == G_NEW) |
307 | return 0; | 307 | return 0; |
308 | return 1; | 308 | return 1; |
309 | } | 309 | } |
@@ -510,7 +510,8 @@ static void checkrefs (global_State *g, GCObject *o) { | |||
510 | ** * objects must be old enough for their lists ('listage'). | 510 | ** * objects must be old enough for their lists ('listage'). |
511 | ** * old objects cannot be white. | 511 | ** * old objects cannot be white. |
512 | ** * old objects must be black, except for 'touched1', 'old0', | 512 | ** * old objects must be black, except for 'touched1', 'old0', |
513 | ** threads, and open upvalues. | 513 | ** threads, and open upvalues. |
514 | ** * 'touched1' objects must be gray. | ||
514 | */ | 515 | */ |
515 | static void checkobject (global_State *g, GCObject *o, int maybedead, | 516 | static void checkobject (global_State *g, GCObject *o, int maybedead, |
516 | int listage) { | 517 | int listage) { |
@@ -520,14 +521,15 @@ static void checkobject (global_State *g, GCObject *o, int maybedead, | |||
520 | assert(g->gcstate != GCSpause || iswhite(o)); | 521 | assert(g->gcstate != GCSpause || iswhite(o)); |
521 | if (g->gckind == KGC_GEN) { /* generational mode? */ | 522 | if (g->gckind == KGC_GEN) { /* generational mode? */ |
522 | assert(getage(o) >= listage); | 523 | assert(getage(o) >= listage); |
523 | assert(!iswhite(o) || !isold(o)); | ||
524 | if (isold(o)) { | 524 | if (isold(o)) { |
525 | assert(!iswhite(o)); | ||
525 | assert(isblack(o) || | 526 | assert(isblack(o) || |
526 | getage(o) == G_TOUCHED1 || | 527 | getage(o) == G_TOUCHED1 || |
527 | getage(o) == G_OLD0 || | 528 | getage(o) == G_OLD0 || |
528 | o->tt == LUA_VTHREAD || | 529 | o->tt == LUA_VTHREAD || |
529 | (o->tt == LUA_VUPVAL && upisopen(gco2upv(o)))); | 530 | (o->tt == LUA_VUPVAL && upisopen(gco2upv(o)))); |
530 | } | 531 | } |
532 | assert(getage(o) != G_TOUCHED1 || isgray(o)); | ||
531 | } | 533 | } |
532 | checkrefs(g, o); | 534 | checkrefs(g, o); |
533 | } | 535 | } |