aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-11-22 11:12:07 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-11-22 11:12:07 -0200
commit29ede6aa13144ff7b69c57a87be1ee93f57ae896 (patch)
treeadcfb5dcff7db55481cd675349e23dec0e63c939 /lgc.c
parent951897c09319ae5474a4b86bb7d615136577caa0 (diff)
downloadlua-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.c123
1 files changed, 62 insertions, 61 deletions
diff --git a/lgc.c b/lgc.c
index a71693e1..ad82c411 100644
--- a/lgc.c
+++ b/lgc.c
@@ -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
22static int markobject (TObject *o); 23static 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
30static void protomark (TProtoFunc *f) { 31static 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
41static void closuremark (Closure *f) { 42static 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
51static void hashmark (Hash *h) { 52static 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
66static void travglobal (void) { 67static 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
78static void travstack (void) { 79static 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
85static void travlock (void) { 86static 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
94static int markobject (TObject *o) { 95static 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
114static void collectproto (void) { 115static 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
130static void collectclosure (void) { 131static 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
146static void collecttable (void) { 147static 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*/
166static void clear_global_list (int limit) { 167static 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*/
181static void collectstring (int limit) { 182static 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
216static void tableTM (void) { 217static 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
233static void markall (void) { 234static 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
241void luaC_collect (int all) { 242void 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
251long lua_collectgarbage (long limit) { 252long 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
267void luaC_checkGC (void) { 268void 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