diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-11-22 11:12:07 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-11-22 11:12:07 -0200 |
commit | 29ede6aa13144ff7b69c57a87be1ee93f57ae896 (patch) | |
tree | adcfb5dcff7db55481cd675349e23dec0e63c939 /lgc.c | |
parent | 951897c09319ae5474a4b86bb7d615136577caa0 (diff) | |
download | lua-29ede6aa13144ff7b69c57a87be1ee93f57ae896.tar.gz lua-29ede6aa13144ff7b69c57a87be1ee93f57ae896.tar.bz2 lua-29ede6aa13144ff7b69c57a87be1ee93f57ae896.zip |
first implementation of multiple states (reentrant code).
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 123 |
1 files changed, 62 insertions, 61 deletions
@@ -1,9 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.30 1999/11/04 17:22:26 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.31 1999/11/10 15:40:46 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 | */ |
6 | 6 | ||
7 | #define LUA_REENTRANT | ||
7 | 8 | ||
8 | #include "ldo.h" | 9 | #include "ldo.h" |
9 | #include "lfunc.h" | 10 | #include "lfunc.h" |
@@ -19,91 +20,91 @@ | |||
19 | 20 | ||
20 | 21 | ||
21 | 22 | ||
22 | static int markobject (TObject *o); | 23 | static int markobject (lua_State *L, TObject *o); |
23 | 24 | ||
24 | 25 | ||
25 | /* mark a string; marks bigger than 1 cannot be changed */ | 26 | /* mark a string; marks bigger than 1 cannot be changed */ |
26 | #define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} | 27 | #define strmark(L, s) {if ((s)->marked == 0) (s)->marked = 1;} |
27 | 28 | ||
28 | 29 | ||
29 | 30 | ||
30 | static void protomark (TProtoFunc *f) { | 31 | static void protomark (lua_State *L, TProtoFunc *f) { |
31 | if (!f->marked) { | 32 | if (!f->marked) { |
32 | int i; | 33 | int i; |
33 | f->marked = 1; | 34 | f->marked = 1; |
34 | strmark(f->source); | 35 | strmark(L, f->source); |
35 | for (i=f->nconsts-1; i>=0; i--) | 36 | for (i=f->nconsts-1; i>=0; i--) |
36 | markobject(&f->consts[i]); | 37 | markobject(L, &f->consts[i]); |
37 | } | 38 | } |
38 | } | 39 | } |
39 | 40 | ||
40 | 41 | ||
41 | static void closuremark (Closure *f) { | 42 | static void closuremark (lua_State *L, Closure *f) { |
42 | if (!f->marked) { | 43 | if (!f->marked) { |
43 | int i; | 44 | int i; |
44 | f->marked = 1; | 45 | f->marked = 1; |
45 | for (i=f->nelems; i>=0; i--) | 46 | for (i=f->nelems; i>=0; i--) |
46 | markobject(&f->consts[i]); | 47 | markobject(L, &f->consts[i]); |
47 | } | 48 | } |
48 | } | 49 | } |
49 | 50 | ||
50 | 51 | ||
51 | static void hashmark (Hash *h) { | 52 | static void hashmark (lua_State *L, Hash *h) { |
52 | if (!h->marked) { | 53 | if (!h->marked) { |
53 | int i; | 54 | int i; |
54 | h->marked = 1; | 55 | h->marked = 1; |
55 | for (i=h->size-1; i>=0; i--) { | 56 | for (i=h->size-1; i>=0; i--) { |
56 | Node *n = node(h,i); | 57 | Node *n = node(L, h,i); |
57 | if (ttype(key(n)) != LUA_T_NIL) { | 58 | if (ttype(key(L, n)) != LUA_T_NIL) { |
58 | markobject(&n->key); | 59 | markobject(L, &n->key); |
59 | markobject(&n->val); | 60 | markobject(L, &n->val); |
60 | } | 61 | } |
61 | } | 62 | } |
62 | } | 63 | } |
63 | } | 64 | } |
64 | 65 | ||
65 | 66 | ||
66 | static void travglobal (void) { | 67 | static void travglobal (lua_State *L) { |
67 | GlobalVar *gv; | 68 | GlobalVar *gv; |
68 | for (gv=L->rootglobal; gv; gv=gv->next) { | 69 | for (gv=L->rootglobal; gv; gv=gv->next) { |
69 | LUA_ASSERT(gv->name->u.s.gv == gv, "inconsistent global name"); | 70 | LUA_ASSERT(L, gv->name->u.s.gv == gv, "inconsistent global name"); |
70 | if (gv->value.ttype != LUA_T_NIL) { | 71 | if (gv->value.ttype != LUA_T_NIL) { |
71 | strmark(gv->name); /* cannot collect non nil global variables */ | 72 | strmark(L, gv->name); /* cannot collect non nil global variables */ |
72 | markobject(&gv->value); | 73 | markobject(L, &gv->value); |
73 | } | 74 | } |
74 | } | 75 | } |
75 | } | 76 | } |
76 | 77 | ||
77 | 78 | ||
78 | static void travstack (void) { | 79 | static void travstack (lua_State *L) { |
79 | StkId i; | 80 | StkId i; |
80 | for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) | 81 | for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--) |
81 | markobject(L->stack.stack+i); | 82 | markobject(L, L->stack.stack+i); |
82 | } | 83 | } |
83 | 84 | ||
84 | 85 | ||
85 | static void travlock (void) { | 86 | static void travlock (lua_State *L) { |
86 | int i; | 87 | int i; |
87 | for (i=0; i<L->refSize; i++) { | 88 | for (i=0; i<L->refSize; i++) { |
88 | if (L->refArray[i].st == LOCK) | 89 | if (L->refArray[i].st == LOCK) |
89 | markobject(&L->refArray[i].o); | 90 | markobject(L, &L->refArray[i].o); |
90 | } | 91 | } |
91 | } | 92 | } |
92 | 93 | ||
93 | 94 | ||
94 | static int markobject (TObject *o) { | 95 | static int markobject (lua_State *L, TObject *o) { |
95 | switch (ttype(o)) { | 96 | switch (ttype(o)) { |
96 | case LUA_T_USERDATA: case LUA_T_STRING: | 97 | case LUA_T_USERDATA: case LUA_T_STRING: |
97 | strmark(tsvalue(o)); | 98 | strmark(L, tsvalue(o)); |
98 | break; | 99 | break; |
99 | case LUA_T_ARRAY: | 100 | case LUA_T_ARRAY: |
100 | hashmark(avalue(o)); | 101 | hashmark(L, avalue(o)); |
101 | break; | 102 | break; |
102 | case LUA_T_CLOSURE: case LUA_T_CLMARK: | 103 | case LUA_T_CLOSURE: case LUA_T_CLMARK: |
103 | closuremark(o->value.cl); | 104 | closuremark(L, o->value.cl); |
104 | break; | 105 | break; |
105 | case LUA_T_PROTO: case LUA_T_PMARK: | 106 | case LUA_T_PROTO: case LUA_T_PMARK: |
106 | protomark(o->value.tf); | 107 | protomark(L, o->value.tf); |
107 | break; | 108 | break; |
108 | default: break; /* numbers, cprotos, etc */ | 109 | default: break; /* numbers, cprotos, etc */ |
109 | } | 110 | } |
@@ -111,7 +112,7 @@ static int markobject (TObject *o) { | |||
111 | } | 112 | } |
112 | 113 | ||
113 | 114 | ||
114 | static void collectproto (void) { | 115 | static void collectproto (lua_State *L) { |
115 | TProtoFunc **p = &L->rootproto; | 116 | TProtoFunc **p = &L->rootproto; |
116 | TProtoFunc *next; | 117 | TProtoFunc *next; |
117 | while ((next = *p) != NULL) { | 118 | while ((next = *p) != NULL) { |
@@ -121,13 +122,13 @@ static void collectproto (void) { | |||
121 | } | 122 | } |
122 | else { | 123 | else { |
123 | *p = next->next; | 124 | *p = next->next; |
124 | luaF_freeproto(next); | 125 | luaF_freeproto(L, next); |
125 | } | 126 | } |
126 | } | 127 | } |
127 | } | 128 | } |
128 | 129 | ||
129 | 130 | ||
130 | static void collectclosure (void) { | 131 | static void collectclosure (lua_State *L) { |
131 | Closure **p = &L->rootcl; | 132 | Closure **p = &L->rootcl; |
132 | Closure *next; | 133 | Closure *next; |
133 | while ((next = *p) != NULL) { | 134 | while ((next = *p) != NULL) { |
@@ -137,13 +138,13 @@ static void collectclosure (void) { | |||
137 | } | 138 | } |
138 | else { | 139 | else { |
139 | *p = next->next; | 140 | *p = next->next; |
140 | luaF_freeclosure(next); | 141 | luaF_freeclosure(L, next); |
141 | } | 142 | } |
142 | } | 143 | } |
143 | } | 144 | } |
144 | 145 | ||
145 | 146 | ||
146 | static void collecttable (void) { | 147 | static void collecttable (lua_State *L) { |
147 | Hash **p = &L->roottable; | 148 | Hash **p = &L->roottable; |
148 | Hash *next; | 149 | Hash *next; |
149 | while ((next = *p) != NULL) { | 150 | while ((next = *p) != NULL) { |
@@ -153,7 +154,7 @@ static void collecttable (void) { | |||
153 | } | 154 | } |
154 | else { | 155 | else { |
155 | *p = next->next; | 156 | *p = next->next; |
156 | luaH_free(next); | 157 | luaH_free(L, next); |
157 | } | 158 | } |
158 | } | 159 | } |
159 | } | 160 | } |
@@ -163,7 +164,7 @@ static void collecttable (void) { | |||
163 | ** remove from the global list globals whose names will be collected | 164 | ** remove from the global list globals whose names will be collected |
164 | ** (the global itself is freed when its name is freed) | 165 | ** (the global itself is freed when its name is freed) |
165 | */ | 166 | */ |
166 | static void clear_global_list (int limit) { | 167 | static void clear_global_list (lua_State *L, int limit) { |
167 | GlobalVar **p = &L->rootglobal; | 168 | GlobalVar **p = &L->rootglobal; |
168 | GlobalVar *next; | 169 | GlobalVar *next; |
169 | while ((next = *p) != NULL) { | 170 | while ((next = *p) != NULL) { |
@@ -176,13 +177,13 @@ static void clear_global_list (int limit) { | |||
176 | /* | 177 | /* |
177 | ** collect all elements with `marked' < `limit'. | 178 | ** collect all elements with `marked' < `limit'. |
178 | ** with limit=1, that means all unmarked elements; | 179 | ** with limit=1, that means all unmarked elements; |
179 | ** with limit=MAX_INT, that means all elements (but EMPTY). | 180 | ** with limit=MAX_INT, that means all elements. |
180 | */ | 181 | */ |
181 | static void collectstring (int limit) { | 182 | static void collectstring (lua_State *L, int limit) { |
182 | TObject o; /* to call userdata 'gc' tag method */ | 183 | TObject o; /* to call userdata 'gc' tag method */ |
183 | int i; | 184 | int i; |
184 | ttype(&o) = LUA_T_USERDATA; | 185 | ttype(&o) = LUA_T_USERDATA; |
185 | clear_global_list(limit); | 186 | clear_global_list(L, limit); |
186 | for (i=0; i<NUM_HASHS; i++) { /* for each hash table */ | 187 | for (i=0; i<NUM_HASHS; i++) { /* for each hash table */ |
187 | stringtable *tb = &L->string_root[i]; | 188 | stringtable *tb = &L->string_root[i]; |
188 | int j; | 189 | int j; |
@@ -198,74 +199,74 @@ static void collectstring (int limit) { | |||
198 | else { /* collect */ | 199 | else { /* collect */ |
199 | if (next->constindex == -1) { /* is userdata? */ | 200 | if (next->constindex == -1) { /* is userdata? */ |
200 | tsvalue(&o) = next; | 201 | tsvalue(&o) = next; |
201 | luaD_gcIM(&o); | 202 | luaD_gcIM(L, &o); |
202 | } | 203 | } |
203 | *p = next->nexthash; | 204 | *p = next->nexthash; |
204 | luaS_free(next); | 205 | luaS_free(L, next); |
205 | tb->nuse--; | 206 | tb->nuse--; |
206 | } | 207 | } |
207 | } | 208 | } |
208 | } | 209 | } |
209 | if ((tb->nuse+1)*6 < tb->size) | 210 | if ((tb->nuse+1)*6 < tb->size) |
210 | luaS_grow(tb); /* table is too big; `grow' it to a smaller size */ | 211 | luaS_grow(L, tb); /* table is too big; `grow' it to a smaller size */ |
211 | } | 212 | } |
212 | } | 213 | } |
213 | 214 | ||
214 | 215 | ||
215 | #ifdef LUA_COMPAT_GC | 216 | #ifdef LUA_COMPAT_GC |
216 | static void tableTM (void) { | 217 | static void tableTM (lua_State *L) { |
217 | Hash *p; | 218 | Hash *p; |
218 | TObject o; | 219 | TObject o; |
219 | ttype(&o) = LUA_T_ARRAY; | 220 | ttype(&o) = LUA_T_ARRAY; |
220 | for (p = L->roottable; p; p = p->next) { | 221 | for (p = L->roottable; p; p = p->next) { |
221 | if (!p->marked) { | 222 | if (!p->marked) { |
222 | avalue(&o) = p; | 223 | avalue(&o) = p; |
223 | luaD_gcIM(&o); | 224 | luaD_gcIM(L, &o); |
224 | } | 225 | } |
225 | } | 226 | } |
226 | } | 227 | } |
227 | #else | 228 | #else |
228 | #define tableTM() /* do nothing */ | 229 | #define tableTM(L) /* do nothing */ |
229 | #endif | 230 | #endif |
230 | 231 | ||
231 | 232 | ||
232 | 233 | ||
233 | static void markall (void) { | 234 | static void markall (lua_State *L) { |
234 | travstack(); /* mark stack objects */ | 235 | travstack(L); /* mark stack objects */ |
235 | travglobal(); /* mark global variable values and names */ | 236 | travglobal(L); /* mark global variable values and names */ |
236 | travlock(); /* mark locked objects */ | 237 | travlock(L); /* mark locked objects */ |
237 | luaT_travtagmethods(markobject); /* mark tag methods */ | 238 | luaT_travtagmethods(L, markobject); /* mark tag methods */ |
238 | } | 239 | } |
239 | 240 | ||
240 | 241 | ||
241 | void luaC_collect (int all) { | 242 | void luaC_collect (lua_State *L, int all) { |
242 | L->GCthreshold *= 4; /* to avoid GC during GC */ | 243 | L->GCthreshold *= 4; /* to avoid GC during GC */ |
243 | tableTM(); /* call TM for tables (if LUA_COMPAT_GC) */ | 244 | tableTM(L); /* call TM for tables (if LUA_COMPAT_GC) */ |
244 | collecttable(); | 245 | collecttable(L); |
245 | collectstring(all?MAX_INT:1); | 246 | collectstring(L, all?MAX_INT:1); |
246 | collectproto(); | 247 | collectproto(L); |
247 | collectclosure(); | 248 | collectclosure(L); |
248 | } | 249 | } |
249 | 250 | ||
250 | 251 | ||
251 | long lua_collectgarbage (long limit) { | 252 | long lua_collectgarbage (lua_State *L, long limit) { |
252 | unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */ | 253 | unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */ |
253 | markall(); | 254 | markall(L); |
254 | luaR_invalidaterefs(); | 255 | luaR_invalidaterefs(L); |
255 | luaC_collect(0); | 256 | luaC_collect(L, 0); |
256 | luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */ | 257 | luaD_gcIM(L, &luaO_nilobject); /* GC tag method for nil (signal end of GC) */ |
257 | recovered = recovered - L->nblocks; | 258 | recovered = recovered - L->nblocks; |
258 | L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; | 259 | L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; |
259 | if (L->Mbuffsize > L->Mbuffnext*4) { /* is buffer too big? */ | 260 | if (L->Mbuffsize > L->Mbuffnext*4) { /* is buffer too big? */ |
260 | L->Mbuffsize /= 2; /* still larger than Mbuffnext*2 */ | 261 | L->Mbuffsize /= 2; /* still larger than Mbuffnext*2 */ |
261 | luaM_reallocvector(L->Mbuffer, L->Mbuffsize, char); | 262 | luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char); |
262 | } | 263 | } |
263 | return recovered; | 264 | return recovered; |
264 | } | 265 | } |
265 | 266 | ||
266 | 267 | ||
267 | void luaC_checkGC (void) { | 268 | void luaC_checkGC (lua_State *L) { |
268 | if (L->nblocks >= L->GCthreshold) | 269 | if (L->nblocks >= L->GCthreshold) |
269 | lua_collectgarbage(0); | 270 | lua_collectgarbage(L, 0); |
270 | } | 271 | } |
271 | 272 | ||