aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-10-02 11:47:43 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-10-02 11:47:43 -0300
commit78bc8e553d4190fc3b90be5b621fc0f3507586ef (patch)
tree9bd9317e1a56960b944549d44a20b91024574c19
parentdad808a73a98a23729614b8814728d76b4e5d577 (diff)
downloadlua-78bc8e553d4190fc3b90be5b621fc0f3507586ef.tar.gz
lua-78bc8e553d4190fc3b90be5b621fc0f3507586ef.tar.bz2
lua-78bc8e553d4190fc3b90be5b621fc0f3507586ef.zip
new API for garbage collector
-rw-r--r--lapi.c33
-rw-r--r--lbaselib.c18
-rw-r--r--ldo.c5
-rw-r--r--lgc.c68
-rw-r--r--lgc.h4
-rw-r--r--ltests.c5
-rw-r--r--lua.h10
-rw-r--r--lvm.c6
8 files changed, 87 insertions, 62 deletions
diff --git a/lapi.c b/lapi.c
index 09ab8f20..f2cd0b0d 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 1.100 2000/09/27 12:51:39 roberto Exp roberto $ 2** $Id: lapi.c,v 1.101 2000/09/29 12:42:13 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -155,7 +155,6 @@ double lua_tonumber (lua_State *L, int index) {
155} 155}
156 156
157const char *lua_tostring (lua_State *L, int index) { 157const char *lua_tostring (lua_State *L, int index) {
158 luaC_checkGC(L); /* `tostring' may create a new string */
159 access(L, index, (tostring(L, o) == 0), NULL, svalue(o)); 158 access(L, index, (tostring(L, o) == 0), NULL, svalue(o));
160} 159}
161 160
@@ -203,7 +202,6 @@ void lua_pushnumber (lua_State *L, double n) {
203 202
204 203
205void lua_pushlstring (lua_State *L, const char *s, size_t len) { 204void lua_pushlstring (lua_State *L, const char *s, size_t len) {
206 luaC_checkGC(L);
207 tsvalue(L->top) = luaS_newlstr(L, s, len); 205 tsvalue(L->top) = luaS_newlstr(L, s, len);
208 ttype(L->top) = TAG_STRING; 206 ttype(L->top) = TAG_STRING;
209 api_incr_top(L); 207 api_incr_top(L);
@@ -219,13 +217,11 @@ void lua_pushstring (lua_State *L, const char *s) {
219 217
220 218
221void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { 219void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
222 luaC_checkGC(L);
223 luaV_Cclosure(L, fn, n); 220 luaV_Cclosure(L, fn, n);
224} 221}
225 222
226 223
227void lua_pushusertag (lua_State *L, void *u, int tag) { /* ORDER LUA_T */ 224void lua_pushusertag (lua_State *L, void *u, int tag) { /* ORDER LUA_T */
228 luaC_checkGC(L);
229 if (tag != LUA_ANYTAG && tag != TAG_USERDATA && tag < NUM_TAGS) 225 if (tag != LUA_ANYTAG && tag != TAG_USERDATA && tag < NUM_TAGS)
230 luaO_verror(L, "invalid tag for a userdata (%d)", tag); 226 luaO_verror(L, "invalid tag for a userdata (%d)", tag);
231 tsvalue(L->top) = luaS_createudata(L, u, tag); 227 tsvalue(L->top) = luaS_createudata(L, u, tag);
@@ -292,7 +288,6 @@ int lua_getref (lua_State *L, int ref) {
292 288
293 289
294void lua_newtable (lua_State *L) { 290void lua_newtable (lua_State *L) {
295 luaC_checkGC(L);
296 hvalue(L->top) = luaH_new(L, 0); 291 hvalue(L->top) = luaH_new(L, 0);
297 ttype(L->top) = TAG_TABLE; 292 ttype(L->top) = TAG_TABLE;
298 api_incr_top(L); 293 api_incr_top(L);
@@ -377,6 +372,31 @@ void lua_rawcall (lua_State *L, int nargs, int nresults) {
377 372
378 373
379/* 374/*
375** Garbage-collection functions
376*/
377
378/* GC values are expressed in Kbytes: #bytes/2^10 */
379#define GCscale(x) ((int)((x)>>10))
380#define GCunscale(x) ((unsigned long)(x)<<10)
381
382int lua_getgcthreshold (lua_State *L) {
383 return GCscale(L->GCthreshold);
384}
385
386int lua_getgccount (lua_State *L) {
387 return GCscale(L->nblocks);
388}
389
390void lua_setgcthreshold (lua_State *L, int newthreshold) {
391 if (newthreshold > GCscale(ULONG_MAX))
392 L->GCthreshold = ULONG_MAX;
393 else
394 L->GCthreshold = GCunscale(newthreshold);
395 luaC_checkGC(L);
396}
397
398
399/*
380** miscellaneous functions 400** miscellaneous functions
381*/ 401*/
382 402
@@ -449,5 +469,6 @@ void lua_concat (lua_State *L, int n) {
449 StkId top = L->top; 469 StkId top = L->top;
450 luaV_strconc(L, n, top); 470 luaV_strconc(L, n, top);
451 L->top = top-(n-1); 471 L->top = top-(n-1);
472 luaC_checkGC(L);
452} 473}
453 474
diff --git a/lbaselib.c b/lbaselib.c
index ee102e36..1a3031ac 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.5 2000/09/14 14:09:31 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.6 2000/09/20 12:54:17 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -183,10 +183,8 @@ static int luaB_settagmethod (lua_State *L) {
183 const char *event = luaL_check_string(L, 2); 183 const char *event = luaL_check_string(L, 2);
184 luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3, 184 luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3,
185 "function or nil expected"); 185 "function or nil expected");
186 lua_pushnil(L); /* to get its tag */ 186 if (strcmp(event, "gc") == 0)
187 if (strcmp(event, "gc") == 0 && tag != lua_tag(L, -1))
188 lua_error(L, "deprecated use: cannot set the `gc' tag method from Lua"); 187 lua_error(L, "deprecated use: cannot set the `gc' tag method from Lua");
189 lua_pop(L, 1); /* remove the nil */
190 lua_settagmethod(L, tag, event); 188 lua_settagmethod(L, tag, event);
191 return 1; 189 return 1;
192} 190}
@@ -197,9 +195,16 @@ static int luaB_gettagmethod (lua_State *L) {
197} 195}
198 196
199 197
198static int luaB_gcinfo (lua_State *L) {
199 lua_pushnumber(L, lua_getgccount(L));
200 lua_pushnumber(L, lua_getgcthreshold(L));
201 return 2;
202}
203
204
200static int luaB_collectgarbage (lua_State *L) { 205static int luaB_collectgarbage (lua_State *L) {
201 lua_pushnumber(L, lua_collectgarbage(L, luaL_opt_int(L, 1, 0))); 206 lua_setgcthreshold(L, luaL_opt_int(L, 1, 0));
202 return 1; 207 return 0;
203} 208}
204 209
205 210
@@ -601,6 +606,7 @@ static const struct luaL_reg base_funcs[] = {
601 {"error", luaB_error}, 606 {"error", luaB_error},
602 {"foreach", luaB_foreach}, 607 {"foreach", luaB_foreach},
603 {"foreachi", luaB_foreachi}, 608 {"foreachi", luaB_foreachi},
609 {"gcinfo", luaB_gcinfo},
604 {"getglobal", luaB_getglobal}, 610 {"getglobal", luaB_getglobal},
605 {"gettagmethod", luaB_gettagmethod}, 611 {"gettagmethod", luaB_gettagmethod},
606 {"globals", luaB_globals}, 612 {"globals", luaB_globals},
diff --git a/ldo.c b/ldo.c
index 283c3cdf..ebf08346 100644
--- a/ldo.c
+++ b/ldo.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldo.c,v 1.97 2000/09/25 16:22:42 roberto Exp roberto $ 2** $Id: ldo.c,v 1.98 2000/09/29 12:42:13 roberto Exp roberto $
3** Stack and Call structure of Lua 3** Stack and Call structure of Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -197,6 +197,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) {
197 nResults--; 197 nResults--;
198 } 198 }
199 L->top = func; 199 L->top = func;
200 luaC_checkGC(L);
200} 201}
201 202
202 203
@@ -366,12 +367,14 @@ int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) {
366 StkId oldCbase = L->Cbase; 367 StkId oldCbase = L->Cbase;
367 StkId oldtop = L->top; 368 StkId oldtop = L->top;
368 struct lua_longjmp lj; 369 struct lua_longjmp lj;
370 int allowhooks = L->allowhooks;
369 lj.status = 0; 371 lj.status = 0;
370 lj.previous = L->errorJmp; /* chain new error handler */ 372 lj.previous = L->errorJmp; /* chain new error handler */
371 L->errorJmp = &lj; 373 L->errorJmp = &lj;
372 if (setjmp(lj.b) == 0) 374 if (setjmp(lj.b) == 0)
373 (*f)(L, ud); 375 (*f)(L, ud);
374 else { /* an error occurred: restore the state */ 376 else { /* an error occurred: restore the state */
377 L->allowhooks = allowhooks;
375 L->Cbase = oldCbase; 378 L->Cbase = oldCbase;
376 L->top = oldtop; 379 L->top = oldtop;
377 restore_stack_limit(L); 380 restore_stack_limit(L);
diff --git a/lgc.c b/lgc.c
index 296179a6..4ff8bf3c 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.67 2000/09/25 14:52:10 roberto Exp roberto $ 2** $Id: lgc.c,v 1.68 2000/09/29 12:42:13 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*/
@@ -235,18 +235,13 @@ static void checktab (lua_State *L, stringtable *tb) {
235} 235}
236 236
237 237
238/* 238static void collectstrings (lua_State *L, int all) {
239** collect all elements with `marked' <= `limit'.
240** with limit=0, that means all unmarked elements;
241** with limit=MAX_INT, that means all elements.
242*/
243static void collectstringtab (lua_State *L, int limit) {
244 int i; 239 int i;
245 for (i=0; i<L->strt.size; i++) { /* for each list */ 240 for (i=0; i<L->strt.size; i++) { /* for each list */
246 TString **p = &L->strt.hash[i]; 241 TString **p = &L->strt.hash[i];
247 TString *next; 242 TString *next;
248 while ((next = *p) != NULL) { 243 while ((next = *p) != NULL) {
249 if ((int)next->marked > limit) { /* preserve? */ 244 if (next->marked && !all) { /* preserve? */
250 if (next->marked < FIXMARK) /* does not change FIXMARKs */ 245 if (next->marked < FIXMARK) /* does not change FIXMARKs */
251 next->marked = 0; 246 next->marked = 0;
252 p = &next->nexthash; 247 p = &next->nexthash;
@@ -263,14 +258,14 @@ static void collectstringtab (lua_State *L, int limit) {
263} 258}
264 259
265 260
266static void collectudatatab (lua_State *L, int all) { 261static void collectudata (lua_State *L, int all) {
267 int i; 262 int i;
268 for (i=0; i<L->udt.size; i++) { /* for each list */ 263 for (i=0; i<L->udt.size; i++) { /* for each list */
269 TString **p = &L->udt.hash[i]; 264 TString **p = &L->udt.hash[i];
270 TString *next; 265 TString *next;
271 while ((next = *p) != NULL) { 266 while ((next = *p) != NULL) {
272 LUA_ASSERT(next->marked <= 1, "udata cannot be fixed"); 267 LUA_ASSERT(next->marked <= 1, "udata cannot be fixed");
273 if ((int)next->marked > all) { /* preserve? */ 268 if (next->marked && !all) { /* preserve? */
274 next->marked = 0; 269 next->marked = 0;
275 p = &next->nexthash; 270 p = &next->nexthash;
276 } 271 }
@@ -289,14 +284,28 @@ static void collectudatatab (lua_State *L, int all) {
289} 284}
290 285
291 286
287#define MINBUFFER 256
288static void checkMbuffer (lua_State *L) {
289 if (L->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */
290 size_t newsize = L->Mbuffsize/2; /* still larger than MINBUFFER */
291 L->nblocks += (newsize - L->Mbuffsize)*sizeof(char);
292 L->Mbuffsize = newsize;
293 luaM_reallocvector(L, L->Mbuffer, newsize, char);
294 }
295}
296
297
292static void callgcTM (lua_State *L, const TObject *o) { 298static void callgcTM (lua_State *L, const TObject *o) {
293 const TObject *im = luaT_getimbyObj(L, o, IM_GC); 299 const TObject *im = luaT_getimbyObj(L, o, IM_GC);
294 if (ttype(im) != TAG_NIL) { 300 if (ttype(im) != TAG_NIL) {
301 int oldah = L->allowhooks;
302 L->allowhooks = 0; /* stop debug hooks during GC tag methods */
295 luaD_checkstack(L, 2); 303 luaD_checkstack(L, 2);
296 *(L->top) = *im; 304 *(L->top) = *im;
297 *(L->top+1) = *o; 305 *(L->top+1) = *o;
298 L->top += 2; 306 L->top += 2;
299 luaD_call(L, L->top-2, 0); 307 luaD_call(L, L->top-2, 0);
308 L->allowhooks = oldah; /* restore hooks */
300 } 309 }
301} 310}
302 311
@@ -305,56 +314,41 @@ static void callgcTMudata (lua_State *L) {
305 int tag; 314 int tag;
306 TObject o; 315 TObject o;
307 ttype(&o) = TAG_USERDATA; 316 ttype(&o) = TAG_USERDATA;
308 for (tag=L->last_tag; tag>=0; tag--) { 317 L->GCthreshold = 2*L->nblocks; /* avoid GC during tag methods */
309 TString *udata = L->IMtable[tag].collected; 318 for (tag=L->last_tag; tag>=0; tag--) { /* for each tag (in reverse order) */
310 L->IMtable[tag].collected = NULL; 319 TString *udata;
311 while (udata) { 320 while ((udata = L->IMtable[tag].collected) != NULL) {
312 TString *next = udata->nexthash; 321 L->IMtable[tag].collected = udata->nexthash; /* remove it from list */
313 tsvalue(&o) = udata; 322 tsvalue(&o) = udata;
314 callgcTM(L, &o); 323 callgcTM(L, &o);
315 luaM_free(L, udata); 324 luaM_free(L, udata);
316 udata = next;
317 } 325 }
318 } 326 }
319} 327}
320 328
321 329
322void luaC_collect (lua_State *L, int all) { 330void luaC_collect (lua_State *L, int all) {
323 int oldah = L->allowhooks; 331 collectudata(L, all);
324 L->allowhooks = 0; /* stop debug hooks during GC */
325 L->GCthreshold *= 4; /* to avoid GC during GC */
326 collectudatatab(L, all);
327 callgcTMudata(L); 332 callgcTMudata(L);
328 collectstringtab(L, all?MAX_INT:0); 333 collectstrings(L, all);
329 collecttable(L); 334 collecttable(L);
330 collectproto(L); 335 collectproto(L);
331 collectclosure(L); 336 collectclosure(L);
332 L->allowhooks = oldah; /* restore hooks */
333} 337}
334 338
335 339
336#define MINBUFFER 256 340static void luaC_collectgarbage (lua_State *L) {
337
338long lua_collectgarbage (lua_State *L, long limit) {
339 unsigned long recovered = L->nblocks; /* to subtract `nblocks' after gc */
340 markall(L); 341 markall(L);
341 invalidaterefs(L); 342 invalidaterefs(L); /* check unlocked references */
342 luaC_collect(L, 0); 343 luaC_collect(L, 0);
343 recovered = recovered - L->nblocks; 344 checkMbuffer(L);
344 L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; 345 L->GCthreshold = 2*L->nblocks; /* set new threshold */
345 if (L->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */
346 size_t diff = L->Mbuffsize/2;
347 L->Mbuffsize -= diff; /* still larger than MINBUFFER */
348 L->nblocks -= diff*sizeof(char);
349 luaM_reallocvector(L, L->Mbuffer, L->Mbuffsize, char);
350 }
351 callgcTM(L, &luaO_nilobject); 346 callgcTM(L, &luaO_nilobject);
352 return recovered;
353} 347}
354 348
355 349
356void luaC_checkGC (lua_State *L) { 350void luaC_checkGC (lua_State *L) {
357 if (L->nblocks >= L->GCthreshold) 351 if (L->nblocks >= L->GCthreshold)
358 lua_collectgarbage(L, 0); 352 luaC_collectgarbage(L);
359} 353}
360 354
diff --git a/lgc.h b/lgc.h
index 7e62f737..73845da9 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 1.6 1999/10/04 17:51:04 roberto Exp roberto $ 2** $Id: lgc.h,v 1.7 1999/11/22 13:12:07 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*/
@@ -11,8 +11,8 @@
11#include "lobject.h" 11#include "lobject.h"
12 12
13 13
14void luaC_checkGC (lua_State *L);
15void luaC_collect (lua_State *L, int all); 14void luaC_collect (lua_State *L, int all);
15void luaC_checkGC (lua_State *L);
16 16
17 17
18#endif 18#endif
diff --git a/ltests.c b/ltests.c
index f84383ce..49717a93 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.44 2000/09/25 16:22:42 roberto Exp roberto $ 2** $Id: ltests.c,v 1.45 2000/09/29 12:42:13 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -166,8 +166,7 @@ static int mem_query (lua_State *L) {
166 lua_pushnumber(L, memdebug_total); 166 lua_pushnumber(L, memdebug_total);
167 lua_pushnumber(L, memdebug_numblocks); 167 lua_pushnumber(L, memdebug_numblocks);
168 lua_pushnumber(L, memdebug_maxmem); 168 lua_pushnumber(L, memdebug_maxmem);
169lua_pushnumber(L, L->nblocks); 169 return 3;
170 return 4;
171 } 170 }
172 else { 171 else {
173 memdebug_memlimit = luaL_check_int(L, 1); 172 memdebug_memlimit = luaL_check_int(L, 1);
diff --git a/lua.h b/lua.h
index a6001be3..fcae18cf 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.69 2000/09/14 14:09:31 roberto Exp roberto $ 2** $Id: lua.h,v 1.70 2000/09/18 19:39:18 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil 4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
5** e-mail: lua@tecgraf.puc-rio.br 5** e-mail: lua@tecgraf.puc-rio.br
@@ -134,6 +134,12 @@ int lua_dostring (lua_State *L, const char *str);
134int lua_dobuffer (lua_State *L, const char *buff, size_t size, 134int lua_dobuffer (lua_State *L, const char *buff, size_t size,
135 const char *name); 135 const char *name);
136 136
137/*
138** Garbage-collection functions
139*/
140int lua_getgcthreshold (lua_State *L);
141int lua_getgccount (lua_State *L);
142void lua_setgcthreshold (lua_State *L, int newthreshold);
137 143
138/* 144/*
139** miscellaneous functions 145** miscellaneous functions
@@ -146,8 +152,6 @@ void lua_error (lua_State *L, const char *s);
146 152
147void lua_unref (lua_State *L, int ref); 153void lua_unref (lua_State *L, int ref);
148 154
149long lua_collectgarbage (lua_State *L, long limit);
150
151int lua_next (lua_State *L, int index); 155int lua_next (lua_State *L, int index);
152int lua_getn (lua_State *L, int index); 156int lua_getn (lua_State *L, int index);
153 157
diff --git a/lvm.c b/lvm.c
index 365fb42d..8d058673 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 1.136 2000/09/20 17:57:08 roberto Exp roberto $ 2** $Id: lvm.c,v 1.137 2000/09/25 14:48:42 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -351,10 +351,8 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
351 lua_Hook linehook = L->linehook; 351 lua_Hook linehook = L->linehook;
352 infovalue(base-1)->pc = &pc; 352 infovalue(base-1)->pc = &pc;
353 luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK); 353 luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK);
354 if (tf->is_vararg) { /* varargs? */ 354 if (tf->is_vararg) /* varargs? */
355 adjust_varargs(L, base, tf->numparams); 355 adjust_varargs(L, base, tf->numparams);
356 luaC_checkGC(L);
357 }
358 else 356 else
359 luaD_adjusttop(L, base, tf->numparams); 357 luaD_adjusttop(L, base, tf->numparams);
360 top = L->top; 358 top = L->top;