summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c10
-rw-r--r--lgc.c84
-rw-r--r--lgc.h13
-rw-r--r--lmem.c5
-rw-r--r--lstate.c14
-rw-r--r--lstate.h6
6 files changed, 77 insertions, 55 deletions
diff --git a/lapi.c b/lapi.c
index 83fe3f40..c8cf819b 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 2.16 2004/08/12 17:02:51 roberto Exp roberto $ 2** $Id: lapi.c,v 2.17 2004/08/17 17:45:45 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*/
@@ -831,7 +831,7 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
831 break; 831 break;
832 } 832 }
833 case LUA_GCRESTART: { 833 case LUA_GCRESTART: {
834 g->GCthreshold = g->nblocks; 834 g->GCthreshold = g->totalbytes;
835 break; 835 break;
836 } 836 }
837 case LUA_GCCOLLECT: { 837 case LUA_GCCOLLECT: {
@@ -840,13 +840,13 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
840 } 840 }
841 case LUA_GCCOUNT: { 841 case LUA_GCCOUNT: {
842 /* GC values are expressed in Kbytes: #bytes/2^10 */ 842 /* GC values are expressed in Kbytes: #bytes/2^10 */
843 res = cast(int, g->nblocks >> 10); 843 res = cast(int, g->totalbytes >> 10);
844 break; 844 break;
845 } 845 }
846 case LUA_GCSTEP: { 846 case LUA_GCSTEP: {
847 lu_mem a = (cast(lu_mem, data) << 10); 847 lu_mem a = (cast(lu_mem, data) << 10);
848 if (a <= g->nblocks) 848 if (a <= g->totalbytes)
849 g->GCthreshold = g->nblocks - a; 849 g->GCthreshold = g->totalbytes - a;
850 else 850 else
851 g->GCthreshold = 0; 851 g->GCthreshold = 0;
852 luaC_step(L); 852 luaC_step(L);
diff --git a/lgc.c b/lgc.c
index 561c6350..94d801ab 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.8 2004/08/10 19:17:23 roberto Exp roberto $ 2** $Id: lgc.c,v 2.9 2004/08/24 20:12:06 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*/
@@ -23,13 +23,11 @@
23#include "ltm.h" 23#include "ltm.h"
24 24
25 25
26#define GCSTEPSIZE (40*sizeof(TValue)) 26#define GCSTEPSIZE 1000
27#define STEPMUL 2 27#define STEPMUL 2
28#define GCSWEEPMAX 40 28#define GCSWEEPMAX 10
29#define GCSWEEPCOST 1 29#define GCSWEEPCOST 30
30#define GCFINALIZECOST (10*sizeof(TValue)) 30#define GCFINALIZECOST 100
31#define WAITNEXTCYCLE (40 * GCSTEPSIZE)
32#define WAITNEXTCYCLEGN (200 * GCSTEPSIZE)
33 31
34 32
35#define FIXEDMASK bitmask(FIXEDBIT) 33#define FIXEDMASK bitmask(FIXEDBIT)
@@ -408,10 +406,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) {
408 global_State *g = G(L); 406 global_State *g = G(L);
409 int whitebit = otherwhite(g); 407 int whitebit = otherwhite(g);
410 int deadmask = whitebit | FIXEDMASK; 408 int deadmask = whitebit | FIXEDMASK;
411 while ((curr = *p) != NULL) { 409 int generational = g->gcgenerational;
410 while ((curr = *p) != NULL && count-- > 0) {
412 if ((curr->gch.marked ^ whitebit) & deadmask) { 411 if ((curr->gch.marked ^ whitebit) & deadmask) {
413 lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); 412 lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));
414 if (!G(L)->gcgenerational || isdead(g, curr)) 413 if (!generational || isdead(g, curr))
415 makewhite(g, curr); 414 makewhite(g, curr);
416 if (curr->gch.tt == LUA_TTHREAD) 415 if (curr->gch.tt == LUA_TTHREAD)
417 sweepwholelist(L, &gco2th(curr)->openupval); 416 sweepwholelist(L, &gco2th(curr)->openupval);
@@ -424,17 +423,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_int32 count) {
424 g->rootgc = curr->gch.next; /* adjust first */ 423 g->rootgc = curr->gch.next; /* adjust first */
425 freeobj(L, curr); 424 freeobj(L, curr);
426 } 425 }
427 if (count-- == 0) break;
428 } 426 }
429 return p; 427 return p;
430} 428}
431 429
432 430
433static void sweepstrings (lua_State *L) {
434 global_State *g = G(L);
435 sweepwholelist(L, &G(L)->strt.hash[g->sweepstrgc++]);
436}
437
438 431
439static void freelist (lua_State *L, GCObject **p) { 432static void freelist (lua_State *L, GCObject **p) {
440 while (*p) { 433 while (*p) {
@@ -532,6 +525,7 @@ static void remarkupvals (global_State *g) {
532 525
533static void atomic (lua_State *L) { 526static void atomic (lua_State *L) {
534 global_State *g = G(L); 527 global_State *g = G(L);
528 int aux;
535 lua_assert(g->gray == NULL); 529 lua_assert(g->gray == NULL);
536 /* remark occasional upvalues of (maybe) dead threads */ 530 /* remark occasional upvalues of (maybe) dead threads */
537 remarkupvals(g); 531 remarkupvals(g);
@@ -554,7 +548,11 @@ static void atomic (lua_State *L) {
554 g->sweepstrgc = 0; 548 g->sweepstrgc = 0;
555 g->sweepgc = &g->rootgc; 549 g->sweepgc = &g->rootgc;
556 g->gcstate = GCSsweepstring; 550 g->gcstate = GCSsweepstring;
557 if (g->gcgenerational++ > 20) g->gcgenerational = 0; 551 aux = g->gcgenerational;
552 g->gcgenerational = (g->estimate <= 4*g->prevestimate/2);
553 if (!aux) /* last collection was full? */
554 g->prevestimate = g->estimate; /* keep estimate of last full collection */
555 g->estimate = g->totalbytes; /* first estimate */
558} 556}
559 557
560 558
@@ -562,6 +560,14 @@ static l_mem singlestep (lua_State *L) {
562 global_State *g = G(L); 560 global_State *g = G(L);
563 /*lua_checkmemory(L);*/ 561 /*lua_checkmemory(L);*/
564 switch (g->gcstate) { 562 switch (g->gcstate) {
563 case GCSpause: {
564 /* start a new collection */
565 if (g->gcgenerational)
566 atomic(L);
567 else
568 markroot(L);
569 return 0;
570 }
565 case GCSpropagate: { 571 case GCSpropagate: {
566 if (g->gray) 572 if (g->gray)
567 return propagatemark(g); 573 return propagatemark(g);
@@ -571,33 +577,31 @@ static l_mem singlestep (lua_State *L) {
571 } 577 }
572 } 578 }
573 case GCSsweepstring: { 579 case GCSsweepstring: {
574 sweepstrings(L); 580 lu_mem old = g->totalbytes;
581 sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
575 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ 582 if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */
576 g->gcstate = GCSsweep; /* end sweep-string phase */ 583 g->gcstate = GCSsweep; /* end sweep-string phase */
584 g->estimate -= old - g->totalbytes;
577 return GCSWEEPCOST; 585 return GCSWEEPCOST;
578 } 586 }
579 case GCSsweep: { 587 case GCSsweep: {
588 lu_mem old = g->totalbytes;
580 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); 589 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
581 if (*g->sweepgc == NULL) { /* nothing more to sweep? */ 590 if (*g->sweepgc == NULL) { /* nothing more to sweep? */
582 checkSizes(L); 591 checkSizes(L);
583 g->gcstate = GCSfinalize; /* end sweep phase */ 592 g->gcstate = GCSfinalize; /* end sweep phase */
584 } 593 }
585 return GCSWEEPCOST; 594 g->estimate -= old - g->totalbytes;
595 return GCSWEEPMAX*GCSWEEPCOST;
586 } 596 }
587 case GCSfinalize: { 597 case GCSfinalize: {
588 if (g->tmudata) { 598 if (g->tmudata) {
589 GCTM(L); 599 GCTM(L);
590 return GCFINALIZECOST; 600 return GCFINALIZECOST;
591 } 601 }
592 else { /* no more `udata' to finalize */ 602 else {
593 if (g->gcgenerational) { 603 g->gcstate = GCSpause; /* end collection */
594 atomic(L); 604 return 0;
595 return WAITNEXTCYCLEGN;
596 }
597 else {
598 markroot(L); /* may restart collection */
599 return WAITNEXTCYCLE;
600 }
601 } 605 }
602 } 606 }
603 default: lua_assert(0); return 0; 607 default: lua_assert(0); return 0;
@@ -607,18 +611,30 @@ static l_mem singlestep (lua_State *L) {
607 611
608void luaC_step (lua_State *L) { 612void luaC_step (lua_State *L) {
609 global_State *g = G(L); 613 global_State *g = G(L);
610 l_mem lim = (g->nblocks - (g->GCthreshold - GCSTEPSIZE)) * STEPMUL; 614 l_mem lim = (g->totalbytes - (g->GCthreshold - GCSTEPSIZE)) * STEPMUL;
615/*printf("step(%c): ", g->gcgenerational?'g':' ');*/
611 do { 616 do {
617 /*printf("%c", "_pswf"[g->gcstate]);*/
612 lim -= singlestep(L); 618 lim -= singlestep(L);
619 if (g->gcstate == GCSpause)
620 break;
613 } while (lim > 0); 621 } while (lim > 0);
614 g->GCthreshold = g->nblocks + GCSTEPSIZE - lim/STEPMUL; 622/*printf("\n");*/
615 lua_assert((long)g->nblocks + (long)GCSTEPSIZE >= lim/STEPMUL); 623 if (g->gcstate != GCSpause)
624 g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/STEPMUL; */
625 else {
626/*printf("---\n");*/
627 lua_assert(g->totalbytes >= g->estimate);
628 g->GCthreshold = 2*g->estimate;
629 if (g->GCthreshold < g->totalbytes + GCSTEPSIZE)
630 g->GCthreshold = g->totalbytes + GCSTEPSIZE;
631 }
616} 632}
617 633
618 634
619void luaC_fullgc (lua_State *L) { 635void luaC_fullgc (lua_State *L) {
620 global_State *g = G(L); 636 global_State *g = G(L);
621 if (g->gcstate == GCSpropagate || g->gcgenerational) { 637 if (g->gcstate <= GCSpropagate || g->gcgenerational) {
622 g->gcgenerational = 0; 638 g->gcgenerational = 0;
623 /* reset sweep marks to sweep all elements (returning them to white) */ 639 /* reset sweep marks to sweep all elements (returning them to white) */
624 g->sweepstrgc = 0; 640 g->sweepstrgc = 0;
@@ -631,6 +647,7 @@ void luaC_fullgc (lua_State *L) {
631 } 647 }
632 /* finish any pending sweep phase */ 648 /* finish any pending sweep phase */
633 while (g->gcstate != GCSfinalize) { 649 while (g->gcstate != GCSfinalize) {
650 lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
634 singlestep(L); 651 singlestep(L);
635 } 652 }
636 markroot(L); 653 markroot(L);
@@ -639,7 +656,8 @@ void luaC_fullgc (lua_State *L) {
639 singlestep(L); 656 singlestep(L);
640 g->gcgenerational = 0; /* keep it in this mode */ 657 g->gcgenerational = 0; /* keep it in this mode */
641 } 658 }
642 g->GCthreshold = g->nblocks + GCSTEPSIZE; 659 lua_assert(g->estimate == g->totalbytes);
660 g->GCthreshold = 2*g->estimate;
643 luaC_callGCTM(L); /* call finalizers */ 661 luaC_callGCTM(L); /* call finalizers */
644} 662}
645 663
@@ -686,7 +704,7 @@ void luaC_linkupval (lua_State *L, UpVal *uv) {
686 } 704 }
687 else { /* sweep phase: sweep it (turning it into white) */ 705 else { /* sweep phase: sweep it (turning it into white) */
688 makewhite(g, o); 706 makewhite(g, o);
689 lua_assert(g->gcstate != GCSfinalize); 707 lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);
690 } 708 }
691 } 709 }
692} 710}
diff --git a/lgc.h b/lgc.h
index c1d102f9..b4097b05 100644
--- a/lgc.h
+++ b/lgc.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.h,v 2.6 2004/08/10 19:17:23 roberto Exp roberto $ 2** $Id: lgc.h,v 2.7 2004/08/24 20:12:06 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*/
@@ -14,10 +14,11 @@
14/* 14/*
15** Possible states of the Garbage Collector 15** Possible states of the Garbage Collector
16*/ 16*/
17#define GCSpropagate 0 17#define GCSpause 0
18#define GCSsweepstring 1 18#define GCSpropagate 1
19#define GCSsweep 2 19#define GCSsweepstring 2
20#define GCSfinalize 3 20#define GCSsweep 3
21#define GCSfinalize 4
21 22
22 23
23/* 24/*
@@ -71,7 +72,7 @@
71#define luaC_white(g) cast(lu_byte, (g)->currentwhite) 72#define luaC_white(g) cast(lu_byte, (g)->currentwhite)
72 73
73 74
74#define luaC_checkGC(L) { if (G(L)->nblocks >= G(L)->GCthreshold) \ 75#define luaC_checkGC(L) { if (G(L)->totalbytes >= G(L)->GCthreshold) \
75 luaC_step(L); } 76 luaC_step(L); }
76 77
77 78
diff --git a/lmem.c b/lmem.c
index 538951f9..5873e8dc 100644
--- a/lmem.c
+++ b/lmem.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lmem.c,v 1.63 2003/11/27 18:18:37 roberto Exp roberto $ 2** $Id: lmem.c,v 1.64 2004/04/30 20:13:38 roberto Exp roberto $
3** Interface to Memory Manager 3** Interface to Memory Manager
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -77,8 +77,7 @@ void *luaM_realloc (lua_State *L, void *block, lu_mem osize, lu_mem nsize) {
77 if (block == NULL && nsize > 0) 77 if (block == NULL && nsize > 0)
78 luaD_throw(L, LUA_ERRMEM); 78 luaD_throw(L, LUA_ERRMEM);
79 lua_assert((nsize == 0) == (block == NULL)); 79 lua_assert((nsize == 0) == (block == NULL));
80 g->nblocks -= osize; 80 g->totalbytes = (g->totalbytes - osize) + nsize;
81 g->nblocks += nsize;
82 return block; 81 return block;
83} 82}
84 83
diff --git a/lstate.c b/lstate.c
index 11f57728..568d8e72 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 2.10 2004/06/17 14:25:31 roberto Exp roberto $ 2** $Id: lstate.c,v 2.11 2004/08/24 20:12:06 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*/
@@ -77,11 +77,12 @@ static void freestack (lua_State *L, lua_State *L1) {
77*/ 77*/
78static void f_luaopen (lua_State *L, void *ud) { 78static void f_luaopen (lua_State *L, void *ud) {
79 Udata *u; /* head of udata list */ 79 Udata *u; /* head of udata list */
80 global_State *g = G(L);
80 UNUSED(ud); 81 UNUSED(ud);
81 u = cast(Udata *, luaM_malloc(L, sizeudata(0))); 82 u = cast(Udata *, luaM_malloc(L, sizeudata(0)));
82 u->uv.len = 0; 83 u->uv.len = 0;
83 u->uv.metatable = NULL; 84 u->uv.metatable = NULL;
84 G(L)->firstudata = obj2gco(u); 85 g->firstudata = obj2gco(u);
85 luaC_link(L, obj2gco(u), LUA_TUSERDATA); 86 luaC_link(L, obj2gco(u), LUA_TUSERDATA);
86 setbit(u->uv.marked, FIXEDBIT); 87 setbit(u->uv.marked, FIXEDBIT);
87 setbit(L->marked, FIXEDBIT); 88 setbit(L->marked, FIXEDBIT);
@@ -93,7 +94,8 @@ static void f_luaopen (lua_State *L, void *ud) {
93 luaT_init(L); 94 luaT_init(L);
94 luaX_init(L); 95 luaX_init(L);
95 luaS_fix(luaS_newliteral(L, MEMERRMSG)); 96 luaS_fix(luaS_newliteral(L, MEMERRMSG));
96 G(L)->GCthreshold = 4*G(L)->nblocks; 97 g->GCthreshold = 4*g->totalbytes;
98 g->prevestimate = g->estimate = g->totalbytes;
97} 99}
98 100
99 101
@@ -128,7 +130,7 @@ static void close_state (lua_State *L) {
128 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); 130 luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
129 luaZ_freebuffer(L, &g->buff); 131 luaZ_freebuffer(L, &g->buff);
130 freestack(L, L); 132 freestack(L, L);
131 lua_assert(g->nblocks == sizeof(LG)); 133 lua_assert(g->totalbytes == sizeof(LG));
132 (*g->realloc)(g->ud, fromstate(L), state_size(LG), 0); 134 (*g->realloc)(g->ud, fromstate(L), state_size(LG), 0);
133} 135}
134 136
@@ -177,7 +179,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
177 setnilvalue(registry(L)); 179 setnilvalue(registry(L));
178 luaZ_initbuffer(L, &g->buff); 180 luaZ_initbuffer(L, &g->buff);
179 g->panic = NULL; 181 g->panic = NULL;
180 g->gcstate = GCSfinalize; 182 g->gcstate = GCSpause;
181 g->gcgenerational = 0; 183 g->gcgenerational = 0;
182 g->rootgc = obj2gco(L); 184 g->rootgc = obj2gco(L);
183 g->sweepstrgc = 0; 185 g->sweepstrgc = 0;
@@ -190,7 +192,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
190 setnilvalue(gkey(g->dummynode)); 192 setnilvalue(gkey(g->dummynode));
191 setnilvalue(gval(g->dummynode)); 193 setnilvalue(gval(g->dummynode));
192 g->dummynode->next = NULL; 194 g->dummynode->next = NULL;
193 g->nblocks = sizeof(LG); 195 g->totalbytes = sizeof(LG);
194 if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { 196 if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {
195 /* memory allocation error: free partial state */ 197 /* memory allocation error: free partial state */
196 close_state(L); 198 close_state(L);
diff --git a/lstate.h b/lstate.h
index 8c85b6f6..d8bda576 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 2.5 2004/06/02 19:07:55 roberto Exp roberto $ 2** $Id: lstate.h,v 2.6 2004/08/24 20:12:06 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*/
@@ -82,7 +82,9 @@ typedef struct global_State {
82 GCObject *tmudata; /* list of userdata to be GC */ 82 GCObject *tmudata; /* list of userdata to be GC */
83 Mbuffer buff; /* temporary buffer for string concatentation */ 83 Mbuffer buff; /* temporary buffer for string concatentation */
84 lu_mem GCthreshold; 84 lu_mem GCthreshold;
85 lu_mem nblocks; /* number of `bytes' currently allocated */ 85 lu_mem totalbytes; /* number of bytes currently allocated */
86 lu_mem estimate; /* an estimate of number of bytes actually in use */
87 lu_mem prevestimate; /* previous estimate */
86 lua_CFunction panic; /* to be called in unprotected errors */ 88 lua_CFunction panic; /* to be called in unprotected errors */
87 TValue _registry; 89 TValue _registry;
88 struct lua_State *mainthread; 90 struct lua_State *mainthread;