diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-04 15:22:42 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-12-04 15:22:42 -0200 |
commit | 9db1942bac5fb509c6e46ccc825351a6be546792 (patch) | |
tree | d9f8091bf61610b7681c10b9b769031fc787f65e | |
parent | c6eac44a9420a26a2f8907dcd5266a6aecdb18ea (diff) | |
download | lua-9db1942bac5fb509c6e46ccc825351a6be546792.tar.gz lua-9db1942bac5fb509c6e46ccc825351a6be546792.tar.bz2 lua-9db1942bac5fb509c6e46ccc825351a6be546792.zip |
sweep of strings also incremental
-rw-r--r-- | lgc.c | 52 | ||||
-rw-r--r-- | lgc.h | 7 | ||||
-rw-r--r-- | lstate.c | 4 | ||||
-rw-r--r-- | lstate.h | 3 | ||||
-rw-r--r-- | lstring.c | 9 |
5 files changed, 50 insertions, 25 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 1.183 2003/12/03 12:30:41 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 1.184 2003/12/03 20:03: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 | */ |
@@ -430,14 +430,14 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all, | |||
430 | GCObject *curr; | 430 | GCObject *curr; |
431 | global_State *g = G(L); | 431 | global_State *g = G(L); |
432 | l_mem lim = *plim; | 432 | l_mem lim = *plim; |
433 | int white = otherwhite(g); | 433 | int dead = otherwhite(g); |
434 | while ((curr = *p) != NULL) { | 434 | while ((curr = *p) != NULL) { |
435 | int mark = curr->gch.marked; | 435 | int mark = curr->gch.marked; |
436 | lua_assert(all || !(mark & g->currentwhite)); | 436 | lua_assert(all || !(mark & g->currentwhite)); |
437 | if (!all && (!(mark & white) || testbit(mark, FIXEDBIT))) { | 437 | lim -= objsize(curr); |
438 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { | ||
438 | makewhite(g, curr); | 439 | makewhite(g, curr); |
439 | p = &curr->gch.next; | 440 | p = &curr->gch.next; |
440 | lim -= objsize(curr); | ||
441 | } | 441 | } |
442 | else { | 442 | else { |
443 | *p = curr->gch.next; | 443 | *p = curr->gch.next; |
@@ -450,27 +450,32 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int all, | |||
450 | } | 450 | } |
451 | 451 | ||
452 | 452 | ||
453 | static void sweepstrings (lua_State *L, int all) { | 453 | static l_mem sweepstrings (lua_State *L, int all, l_mem lim) { |
454 | int i; | 454 | int i; |
455 | global_State *g = G(L); | 455 | global_State *g = G(L); |
456 | int white = otherwhite(g); | 456 | int dead = otherwhite(g); |
457 | for (i = 0; i < g->strt.size; i++) { /* for each list */ | 457 | for (i = g->sweepstrgc; i < g->strt.size; i++) { /* for each list */ |
458 | GCObject *curr; | 458 | GCObject *curr; |
459 | GCObject **p = &G(L)->strt.hash[i]; | 459 | GCObject **p = &G(L)->strt.hash[i]; |
460 | while ((curr = *p) != NULL) { | 460 | while ((curr = *p) != NULL) { |
461 | int mark = curr->gch.marked; | 461 | int mark = curr->gch.marked; |
462 | lu_mem size = sizestring(gcotots(curr)->tsv.len); | ||
462 | lua_assert(all || !(mark & g->currentwhite)); | 463 | lua_assert(all || !(mark & g->currentwhite)); |
463 | if (!all && (!(mark & white) || testbit(mark, FIXEDBIT))) { | 464 | if (!all && (!(mark & dead) || testbit(mark, FIXEDBIT))) { |
464 | makewhite(g, curr); | 465 | makewhite(g, curr); |
465 | p = &curr->gch.next; | 466 | p = &curr->gch.next; |
466 | } | 467 | } |
467 | else { | 468 | else { |
468 | g->strt.nuse--; | 469 | g->strt.nuse--; |
469 | *p = curr->gch.next; | 470 | *p = curr->gch.next; |
470 | luaM_free(L, curr, sizestring(gcotots(curr)->tsv.len)); | 471 | luaM_free(L, curr, size); |
471 | } | 472 | } |
473 | lim -= size; | ||
472 | } | 474 | } |
475 | if (lim <= 0) break; | ||
473 | } | 476 | } |
477 | g->sweepstrgc = i+1; | ||
478 | return lim; | ||
474 | } | 479 | } |
475 | 480 | ||
476 | 481 | ||
@@ -527,7 +532,8 @@ void luaC_callGCTM (lua_State *L) { | |||
527 | 532 | ||
528 | void luaC_sweepall (lua_State *L) { | 533 | void luaC_sweepall (lua_State *L) { |
529 | l_mem dummy = MAXLMEM; | 534 | l_mem dummy = MAXLMEM; |
530 | sweepstrings(L, 1); | 535 | G(L)->sweepstrgc = 0; |
536 | sweepstrings(L, 1, dummy); | ||
531 | sweeplist(L, &G(L)->rootgc, 1, &dummy); | 537 | sweeplist(L, &G(L)->rootgc, 1, &dummy); |
532 | } | 538 | } |
533 | 539 | ||
@@ -540,7 +546,6 @@ static void markroot (lua_State *L) { | |||
540 | makewhite(g, valtogco(g->mainthread)); | 546 | makewhite(g, valtogco(g->mainthread)); |
541 | markobject(g, g->mainthread); | 547 | markobject(g, g->mainthread); |
542 | markvalue(g, registry(L)); | 548 | markvalue(g, registry(L)); |
543 | markobject(g, g->firstudata); | ||
544 | markobject(g, L); /* mark running thread */ | 549 | markobject(g, L); /* mark running thread */ |
545 | g->gcstate = GCSpropagate; | 550 | g->gcstate = GCSpropagate; |
546 | } | 551 | } |
@@ -552,14 +557,25 @@ static void atomic (lua_State *L) { | |||
552 | marktmu(g); /* mark `preserved' userdata */ | 557 | marktmu(g); /* mark `preserved' userdata */ |
553 | propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ | 558 | propagatemarks(g, MAXLMEM); /* remark, to propagate `preserveness' */ |
554 | cleartable(g->weak); /* remove collected objects from weak tables */ | 559 | cleartable(g->weak); /* remove collected objects from weak tables */ |
555 | /* echange current white */ | 560 | /* flip current white */ |
556 | g->currentwhite = otherwhite(g); | 561 | g->currentwhite = otherwhite(g); |
557 | /* first element of root list will be used as temporary head for sweep | 562 | /* first element of root list will be used as temporary head for sweep |
558 | phase, so it won't be seeped */ | 563 | phase, so it won't be swept */ |
559 | makewhite(g, g->rootgc); | 564 | makewhite(g, g->rootgc); |
560 | g->sweepgc = &g->rootgc->gch.next; | 565 | g->sweepgc = &g->rootgc->gch.next; |
561 | sweepstrings(L, 0); | 566 | g->sweepstrgc = 0; |
562 | g->gcstate = GCSsweep; | 567 | g->gcstate = GCSsweepstring; |
568 | } | ||
569 | |||
570 | |||
571 | static void sweepstringstep (lua_State *L) { | ||
572 | global_State *g = G(L); | ||
573 | l_mem lim = sweepstrings(L, 0, GCSTEPSIZE); | ||
574 | if (lim == GCSTEPSIZE) { /* nothing more to sweep? */ | ||
575 | lua_assert(g->sweepstrgc > g->strt.size); | ||
576 | g->sweepstrgc = 0; | ||
577 | g->gcstate = GCSsweep; /* end sweep-string phase */ | ||
578 | } | ||
563 | } | 579 | } |
564 | 580 | ||
565 | 581 | ||
@@ -567,9 +583,8 @@ static void sweepstep (lua_State *L) { | |||
567 | global_State *g = G(L); | 583 | global_State *g = G(L); |
568 | l_mem lim = GCSTEPSIZE; | 584 | l_mem lim = GCSTEPSIZE; |
569 | g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); | 585 | g->sweepgc = sweeplist(L, g->sweepgc, 0, &lim); |
570 | if (lim == GCSTEPSIZE) { /* nothing more to sweep? */ | 586 | if (lim == GCSTEPSIZE) /* nothing more to sweep? */ |
571 | g->gcstate = GCSfinalize; /* end sweep phase */ | 587 | g->gcstate = GCSfinalize; /* end sweep phase */ |
572 | } | ||
573 | } | 588 | } |
574 | 589 | ||
575 | 590 | ||
@@ -582,6 +597,9 @@ void luaC_collectgarbage (lua_State *L) { | |||
582 | propagatemarks(g, GCSTEPSIZE); | 597 | propagatemarks(g, GCSTEPSIZE); |
583 | /* atomic */ | 598 | /* atomic */ |
584 | atomic(L); | 599 | atomic(L); |
600 | /* GCSsweepstring */ | ||
601 | while (g->gcstate == GCSsweepstring) | ||
602 | sweepstringstep(L); | ||
585 | /* GCSsweep */ | 603 | /* GCSsweep */ |
586 | while (g->gcstate == GCSsweep) | 604 | while (g->gcstate == GCSsweep) |
587 | sweepstep(L); | 605 | sweepstep(L); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.h,v 1.25 2003/12/01 16:33:30 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 1.26 2003/12/03 20:03: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 | */ |
@@ -17,8 +17,9 @@ | |||
17 | #define GCSroot 0 | 17 | #define GCSroot 0 |
18 | #define GCSpropagate 1 | 18 | #define GCSpropagate 1 |
19 | #define GCSatomic 2 | 19 | #define GCSatomic 2 |
20 | #define GCSsweep 3 | 20 | #define GCSsweepstring 3 |
21 | #define GCSfinalize 4 | 21 | #define GCSsweep 4 |
22 | #define GCSfinalize 5 | ||
22 | 23 | ||
23 | 24 | ||
24 | /* | 25 | /* |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 1.131 2003/12/03 12:30:41 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.132 2003/12/03 20:03: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 | */ |
@@ -81,6 +81,7 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
81 | u->uv.metatable = NULL; | 81 | u->uv.metatable = NULL; |
82 | G(L)->firstudata = valtogco(u); | 82 | G(L)->firstudata = valtogco(u); |
83 | luaC_link(L, valtogco(u), LUA_TUSERDATA); | 83 | luaC_link(L, valtogco(u), LUA_TUSERDATA); |
84 | setbit(u->uv.marked, FIXEDBIT); | ||
84 | stack_init(L, L); /* init stack */ | 85 | stack_init(L, L); /* init stack */ |
85 | sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ | 86 | sethvalue(gt(L), luaH_new(L, 0, 4)); /* table of globals */ |
86 | sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */ | 87 | sethvalue(registry(L), luaH_new(L, 4, 4)); /* registry */ |
@@ -167,6 +168,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
167 | g->panic = NULL; | 168 | g->panic = NULL; |
168 | g->gcstate = 0; | 169 | g->gcstate = 0; |
169 | g->rootgc = NULL; | 170 | g->rootgc = NULL; |
171 | g->sweepstrgc = 0; | ||
170 | g->currentwhite = bitmask(WHITE0BIT); | 172 | g->currentwhite = bitmask(WHITE0BIT); |
171 | g->firstudata = NULL; | 173 | g->firstudata = NULL; |
172 | g->gray = NULL; | 174 | g->gray = NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 1.116 2003/12/03 12:30:41 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.117 2003/12/03 20:03: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 | */ |
@@ -101,6 +101,7 @@ typedef struct global_State { | |||
101 | GCObject *rootgc; /* list of all collectable objects */ | 101 | GCObject *rootgc; /* list of all collectable objects */ |
102 | GCObject *firstudata; /* udata go to the end of `rootgc' */ | 102 | GCObject *firstudata; /* udata go to the end of `rootgc' */ |
103 | GCObject **sweepgc; /* position of sweep in `rootgc' */ | 103 | GCObject **sweepgc; /* position of sweep in `rootgc' */ |
104 | int sweepstrgc; /* position of sweep in `strt' */ | ||
104 | GCObject *gray; /* list of gray objects */ | 105 | GCObject *gray; /* list of gray objects */ |
105 | GCObject *weak; /* list of weak tables (to be cleared) */ | 106 | GCObject *weak; /* list of weak tables (to be cleared) */ |
106 | GCObject *tmudata; /* list of userdata to be GC */ | 107 | GCObject *tmudata; /* list of userdata to be GC */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 1.82 2003/12/03 12:30:41 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.83 2003/12/03 20:03:07 roberto Exp roberto $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -25,9 +25,12 @@ void luaS_freeall (lua_State *L) { | |||
25 | 25 | ||
26 | 26 | ||
27 | void luaS_resize (lua_State *L, int newsize) { | 27 | void luaS_resize (lua_State *L, int newsize) { |
28 | GCObject **newhash = luaM_newvector(L, newsize, GCObject *); | 28 | GCObject **newhash; |
29 | stringtable *tb = &G(L)->strt; | 29 | stringtable *tb; |
30 | int i; | 30 | int i; |
31 | if (G(L)->sweepstrgc > 0) return; /* cannot resize during GC traverse */ | ||
32 | newhash = luaM_newvector(L, newsize, GCObject *); | ||
33 | tb = &G(L)->strt; | ||
31 | for (i=0; i<newsize; i++) newhash[i] = NULL; | 34 | for (i=0; i<newsize; i++) newhash[i] = NULL; |
32 | /* rehash */ | 35 | /* rehash */ |
33 | for (i=0; i<tb->size; i++) { | 36 | for (i=0; i<tb->size; i++) { |