diff options
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 307 |
1 files changed, 182 insertions, 125 deletions
@@ -18,7 +18,6 @@ | |||
18 | #include "ldo.h" | 18 | #include "ldo.h" |
19 | #include "lfunc.h" | 19 | #include "lfunc.h" |
20 | #include "lgc.h" | 20 | #include "lgc.h" |
21 | #include "llex.h" | ||
22 | #include "lmem.h" | 21 | #include "lmem.h" |
23 | #include "lobject.h" | 22 | #include "lobject.h" |
24 | #include "lstate.h" | 23 | #include "lstate.h" |
@@ -28,13 +27,6 @@ | |||
28 | 27 | ||
29 | 28 | ||
30 | /* | 29 | /* |
31 | ** Number of fixed (luaC_fix) objects in a Lua state: metafield names, | ||
32 | ** plus reserved words, plus "_ENV", plus the memory-error message. | ||
33 | */ | ||
34 | #define NFIXED (TM_N + NUM_RESERVED + 2) | ||
35 | |||
36 | |||
37 | /* | ||
38 | ** Maximum number of elements to sweep in each single step. | 30 | ** Maximum number of elements to sweep in each single step. |
39 | ** (Large enough to dissipate fixed overheads but small enough | 31 | ** (Large enough to dissipate fixed overheads but small enough |
40 | ** to allow small steps for the collector.) | 32 | ** to allow small steps for the collector.) |
@@ -42,6 +34,12 @@ | |||
42 | #define GCSWEEPMAX 20 | 34 | #define GCSWEEPMAX 20 |
43 | 35 | ||
44 | 36 | ||
37 | /* | ||
38 | ** Cost (in work units) of running one finalizer. | ||
39 | */ | ||
40 | #define CWUFIN 10 | ||
41 | |||
42 | |||
45 | /* mask with all color bits */ | 43 | /* mask with all color bits */ |
46 | #define maskcolors (bitmask(BLACKBIT) | WHITEBITS) | 44 | #define maskcolors (bitmask(BLACKBIT) | WHITEBITS) |
47 | 45 | ||
@@ -95,7 +93,7 @@ | |||
95 | 93 | ||
96 | 94 | ||
97 | static void reallymarkobject (global_State *g, GCObject *o); | 95 | static void reallymarkobject (global_State *g, GCObject *o); |
98 | static l_obj atomic (lua_State *L); | 96 | static void atomic (lua_State *L); |
99 | static void entersweep (lua_State *L); | 97 | static void entersweep (lua_State *L); |
100 | 98 | ||
101 | 99 | ||
@@ -112,6 +110,66 @@ static void entersweep (lua_State *L); | |||
112 | #define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) | 110 | #define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) |
113 | 111 | ||
114 | 112 | ||
113 | static size_t objsize (GCObject *o) { | ||
114 | switch (o->tt) { | ||
115 | case LUA_VTABLE: { | ||
116 | /* Fow now, table size does not consider 'haslastfree' */ | ||
117 | Table *t = gco2t(o); | ||
118 | size_t sz = sizeof(Table) | ||
119 | + luaH_realasize(t) * (sizeof(Value) + 1); | ||
120 | if (!isdummy(t)) | ||
121 | sz += sizenode(t) * sizeof(Node); | ||
122 | return sz; | ||
123 | } | ||
124 | case LUA_VLCL: { | ||
125 | LClosure *cl = gco2lcl(o); | ||
126 | return sizeLclosure(cl->nupvalues); | ||
127 | } | ||
128 | case LUA_VCCL: { | ||
129 | CClosure *cl = gco2ccl(o); | ||
130 | return sizeCclosure(cl->nupvalues); | ||
131 | break; | ||
132 | } | ||
133 | case LUA_VUSERDATA: { | ||
134 | Udata *u = gco2u(o); | ||
135 | return sizeudata(u->nuvalue, u->len); | ||
136 | } | ||
137 | case LUA_VPROTO: { | ||
138 | Proto *p = gco2p(o); | ||
139 | size_t sz = sizeof(Proto) | ||
140 | + cast_uint(p->sizep) * sizeof(Proto*) | ||
141 | + cast_uint(p->sizek) * sizeof(TValue) | ||
142 | + cast_uint(p->sizelocvars) * sizeof(LocVar) | ||
143 | + cast_uint(p->sizeupvalues) * sizeof(Upvaldesc); | ||
144 | if (!(p->flag & PF_FIXED)) { | ||
145 | sz += cast_uint(p->sizecode) * sizeof(Instruction) | ||
146 | + cast_uint(p->sizelineinfo) * sizeof(lu_byte) | ||
147 | + cast_uint(p->sizeabslineinfo) * sizeof(AbsLineInfo); | ||
148 | } | ||
149 | return sz; | ||
150 | } | ||
151 | case LUA_VTHREAD: { | ||
152 | lua_State *L1 = gco2th(o); | ||
153 | size_t sz = sizeof(lua_State) + LUA_EXTRASPACE | ||
154 | + cast_uint(L1->nci) * sizeof(CallInfo); | ||
155 | if (L1->stack.p != NULL) | ||
156 | sz += cast_uint(stacksize(L1) + EXTRA_STACK) * sizeof(StackValue); | ||
157 | return sz; | ||
158 | } | ||
159 | case LUA_VSHRSTR: { | ||
160 | TString *ts = gco2ts(o); | ||
161 | return sizestrshr(cast_uint(ts->shrlen)); | ||
162 | } | ||
163 | case LUA_VLNGSTR: { | ||
164 | TString *ts = gco2ts(o); | ||
165 | return luaS_sizelngstr(ts->u.lnglen, ts->shrlen); | ||
166 | } | ||
167 | case LUA_VUPVAL: return sizeof(UpVal); | ||
168 | default: lua_assert(0); return 0; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | |||
115 | static GCObject **getgclist (GCObject *o) { | 173 | static GCObject **getgclist (GCObject *o) { |
116 | switch (o->tt) { | 174 | switch (o->tt) { |
117 | case LUA_VTABLE: return &gco2t(o)->gclist; | 175 | case LUA_VTABLE: return &gco2t(o)->gclist; |
@@ -250,7 +308,6 @@ GCObject *luaC_newobjdt (lua_State *L, lu_byte tt, size_t sz, size_t offset) { | |||
250 | global_State *g = G(L); | 308 | global_State *g = G(L); |
251 | char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); | 309 | char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); |
252 | GCObject *o = cast(GCObject *, p + offset); | 310 | GCObject *o = cast(GCObject *, p + offset); |
253 | g->GCdebt--; | ||
254 | o->marked = luaC_white(g); | 311 | o->marked = luaC_white(g); |
255 | o->tt = tt; | 312 | o->tt = tt; |
256 | o->next = g->allgc; | 313 | o->next = g->allgc; |
@@ -290,7 +347,7 @@ GCObject *luaC_newobj (lua_State *L, lu_byte tt, size_t sz) { | |||
290 | ** (only closures can), and a userdata's metatable must be a table. | 347 | ** (only closures can), and a userdata's metatable must be a table. |
291 | */ | 348 | */ |
292 | static void reallymarkobject (global_State *g, GCObject *o) { | 349 | static void reallymarkobject (global_State *g, GCObject *o) { |
293 | g->GCmarked++; | 350 | g->GCmarked += cast(l_mem, objsize(o)); |
294 | switch (o->tt) { | 351 | switch (o->tt) { |
295 | case LUA_VSHRSTR: | 352 | case LUA_VSHRSTR: |
296 | case LUA_VLNGSTR: { | 353 | case LUA_VLNGSTR: { |
@@ -338,14 +395,10 @@ static void markmt (global_State *g) { | |||
338 | /* | 395 | /* |
339 | ** mark all objects in list of being-finalized | 396 | ** mark all objects in list of being-finalized |
340 | */ | 397 | */ |
341 | static l_obj markbeingfnz (global_State *g) { | 398 | static void markbeingfnz (global_State *g) { |
342 | GCObject *o; | 399 | GCObject *o; |
343 | l_obj count = 0; | 400 | for (o = g->tobefnz; o != NULL; o = o->next) |
344 | for (o = g->tobefnz; o != NULL; o = o->next) { | ||
345 | count++; | ||
346 | markobject(g, o); | 401 | markobject(g, o); |
347 | } | ||
348 | return count; | ||
349 | } | 402 | } |
350 | 403 | ||
351 | 404 | ||
@@ -360,8 +413,7 @@ static l_obj markbeingfnz (global_State *g) { | |||
360 | ** upvalues, as they have nothing to be checked. (If the thread gets an | 413 | ** upvalues, as they have nothing to be checked. (If the thread gets an |
361 | ** upvalue later, it will be linked in the list again.) | 414 | ** upvalue later, it will be linked in the list again.) |
362 | */ | 415 | */ |
363 | static l_obj remarkupvals (global_State *g) { | 416 | static void remarkupvals (global_State *g) { |
364 | l_obj work = 0; | ||
365 | lua_State *thread; | 417 | lua_State *thread; |
366 | lua_State **p = &g->twups; | 418 | lua_State **p = &g->twups; |
367 | while ((thread = *p) != NULL) { | 419 | while ((thread = *p) != NULL) { |
@@ -380,9 +432,7 @@ static l_obj remarkupvals (global_State *g) { | |||
380 | } | 432 | } |
381 | } | 433 | } |
382 | } | 434 | } |
383 | work++; | ||
384 | } | 435 | } |
385 | return work; | ||
386 | } | 436 | } |
387 | 437 | ||
388 | 438 | ||
@@ -401,7 +451,7 @@ static void cleargraylists (global_State *g) { | |||
401 | */ | 451 | */ |
402 | static void restartcollection (global_State *g) { | 452 | static void restartcollection (global_State *g) { |
403 | cleargraylists(g); | 453 | cleargraylists(g); |
404 | g->GCmarked = NFIXED; | 454 | g->GCmarked = 0; |
405 | markobject(g, g->mainthread); | 455 | markobject(g, g->mainthread); |
406 | markvalue(g, &g->l_registry); | 456 | markvalue(g, &g->l_registry); |
407 | markmt(g); | 457 | markmt(g); |
@@ -546,7 +596,7 @@ static void traversestrongtable (global_State *g, Table *h) { | |||
546 | } | 596 | } |
547 | 597 | ||
548 | 598 | ||
549 | static void traversetable (global_State *g, Table *h) { | 599 | static l_mem traversetable (global_State *g, Table *h) { |
550 | const char *weakkey, *weakvalue; | 600 | const char *weakkey, *weakvalue; |
551 | const TValue *mode = gfasttm(g, h->metatable, TM_MODE); | 601 | const TValue *mode = gfasttm(g, h->metatable, TM_MODE); |
552 | TString *smode; | 602 | TString *smode; |
@@ -565,15 +615,17 @@ static void traversetable (global_State *g, Table *h) { | |||
565 | } | 615 | } |
566 | else /* not weak */ | 616 | else /* not weak */ |
567 | traversestrongtable(g, h); | 617 | traversestrongtable(g, h); |
618 | return 1 + sizenode(h) + h->alimit; | ||
568 | } | 619 | } |
569 | 620 | ||
570 | 621 | ||
571 | static void traverseudata (global_State *g, Udata *u) { | 622 | static l_mem traverseudata (global_State *g, Udata *u) { |
572 | int i; | 623 | int i; |
573 | markobjectN(g, u->metatable); /* mark its metatable */ | 624 | markobjectN(g, u->metatable); /* mark its metatable */ |
574 | for (i = 0; i < u->nuvalue; i++) | 625 | for (i = 0; i < u->nuvalue; i++) |
575 | markvalue(g, &u->uv[i].uv); | 626 | markvalue(g, &u->uv[i].uv); |
576 | genlink(g, obj2gco(u)); | 627 | genlink(g, obj2gco(u)); |
628 | return 1 + u->nuvalue; | ||
577 | } | 629 | } |
578 | 630 | ||
579 | 631 | ||
@@ -582,7 +634,7 @@ static void traverseudata (global_State *g, Udata *u) { | |||
582 | ** arrays can be larger than needed; the extra slots are filled with | 634 | ** arrays can be larger than needed; the extra slots are filled with |
583 | ** NULL, so the use of 'markobjectN') | 635 | ** NULL, so the use of 'markobjectN') |
584 | */ | 636 | */ |
585 | static void traverseproto (global_State *g, Proto *f) { | 637 | static l_mem traverseproto (global_State *g, Proto *f) { |
586 | int i; | 638 | int i; |
587 | markobjectN(g, f->source); | 639 | markobjectN(g, f->source); |
588 | for (i = 0; i < f->sizek; i++) /* mark literals */ | 640 | for (i = 0; i < f->sizek; i++) /* mark literals */ |
@@ -593,26 +645,29 @@ static void traverseproto (global_State *g, Proto *f) { | |||
593 | markobjectN(g, f->p[i]); | 645 | markobjectN(g, f->p[i]); |
594 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ | 646 | for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ |
595 | markobjectN(g, f->locvars[i].varname); | 647 | markobjectN(g, f->locvars[i].varname); |
648 | return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars; | ||
596 | } | 649 | } |
597 | 650 | ||
598 | 651 | ||
599 | static void traverseCclosure (global_State *g, CClosure *cl) { | 652 | static l_mem traverseCclosure (global_State *g, CClosure *cl) { |
600 | int i; | 653 | int i; |
601 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | 654 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ |
602 | markvalue(g, &cl->upvalue[i]); | 655 | markvalue(g, &cl->upvalue[i]); |
656 | return 1 + cl->nupvalues; | ||
603 | } | 657 | } |
604 | 658 | ||
605 | /* | 659 | /* |
606 | ** Traverse a Lua closure, marking its prototype and its upvalues. | 660 | ** Traverse a Lua closure, marking its prototype and its upvalues. |
607 | ** (Both can be NULL while closure is being created.) | 661 | ** (Both can be NULL while closure is being created.) |
608 | */ | 662 | */ |
609 | static void traverseLclosure (global_State *g, LClosure *cl) { | 663 | static l_mem traverseLclosure (global_State *g, LClosure *cl) { |
610 | int i; | 664 | int i; |
611 | markobjectN(g, cl->p); /* mark its prototype */ | 665 | markobjectN(g, cl->p); /* mark its prototype */ |
612 | for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ | 666 | for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ |
613 | UpVal *uv = cl->upvals[i]; | 667 | UpVal *uv = cl->upvals[i]; |
614 | markobjectN(g, uv); /* mark upvalue */ | 668 | markobjectN(g, uv); /* mark upvalue */ |
615 | } | 669 | } |
670 | return 1 + cl->nupvalues; | ||
616 | } | 671 | } |
617 | 672 | ||
618 | 673 | ||
@@ -628,13 +683,13 @@ static void traverseLclosure (global_State *g, LClosure *cl) { | |||
628 | ** (which can only happen in generational mode) or if the traverse is in | 683 | ** (which can only happen in generational mode) or if the traverse is in |
629 | ** the propagate phase (which can only happen in incremental mode). | 684 | ** the propagate phase (which can only happen in incremental mode). |
630 | */ | 685 | */ |
631 | static void traversethread (global_State *g, lua_State *th) { | 686 | static l_mem traversethread (global_State *g, lua_State *th) { |
632 | UpVal *uv; | 687 | UpVal *uv; |
633 | StkId o = th->stack.p; | 688 | StkId o = th->stack.p; |
634 | if (isold(th) || g->gcstate == GCSpropagate) | 689 | if (isold(th) || g->gcstate == GCSpropagate) |
635 | linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ | 690 | linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ |
636 | if (o == NULL) | 691 | if (o == NULL) |
637 | return; /* stack not completely built yet */ | 692 | return 0; /* stack not completely built yet */ |
638 | lua_assert(g->gcstate == GCSatomic || | 693 | lua_assert(g->gcstate == GCSatomic || |
639 | th->openupval == NULL || isintwups(th)); | 694 | th->openupval == NULL || isintwups(th)); |
640 | for (; o < th->top.p; o++) /* mark live elements in the stack */ | 695 | for (; o < th->top.p; o++) /* mark live elements in the stack */ |
@@ -652,35 +707,33 @@ static void traversethread (global_State *g, lua_State *th) { | |||
652 | g->twups = th; | 707 | g->twups = th; |
653 | } | 708 | } |
654 | } | 709 | } |
710 | return 1 + (th->top.p - th->stack.p); | ||
655 | } | 711 | } |
656 | 712 | ||
657 | 713 | ||
658 | /* | 714 | /* |
659 | ** traverse one gray object, turning it to black. | 715 | ** traverse one gray object, turning it to black. Return an estimate |
716 | ** of the number of slots traversed. | ||
660 | */ | 717 | */ |
661 | static void propagatemark (global_State *g) { | 718 | static l_mem propagatemark (global_State *g) { |
662 | GCObject *o = g->gray; | 719 | GCObject *o = g->gray; |
663 | nw2black(o); | 720 | nw2black(o); |
664 | g->gray = *getgclist(o); /* remove from 'gray' list */ | 721 | g->gray = *getgclist(o); /* remove from 'gray' list */ |
665 | switch (o->tt) { | 722 | switch (o->tt) { |
666 | case LUA_VTABLE: traversetable(g, gco2t(o)); break; | 723 | case LUA_VTABLE: return traversetable(g, gco2t(o)); |
667 | case LUA_VUSERDATA: traverseudata(g, gco2u(o)); break; | 724 | case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); |
668 | case LUA_VLCL: traverseLclosure(g, gco2lcl(o)); break; | 725 | case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); |
669 | case LUA_VCCL: traverseCclosure(g, gco2ccl(o)); break; | 726 | case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); |
670 | case LUA_VPROTO: traverseproto(g, gco2p(o)); break; | 727 | case LUA_VPROTO: return traverseproto(g, gco2p(o)); |
671 | case LUA_VTHREAD: traversethread(g, gco2th(o)); break; | 728 | case LUA_VTHREAD: return traversethread(g, gco2th(o)); |
672 | default: lua_assert(0); | 729 | default: lua_assert(0); return 0; |
673 | } | 730 | } |
674 | } | 731 | } |
675 | 732 | ||
676 | 733 | ||
677 | static l_obj propagateall (global_State *g) { | 734 | static void propagateall (global_State *g) { |
678 | l_obj work = 0; | 735 | while (g->gray) |
679 | while (g->gray) { | ||
680 | propagatemark(g); | 736 | propagatemark(g); |
681 | work++; | ||
682 | } | ||
683 | return work; | ||
684 | } | 737 | } |
685 | 738 | ||
686 | 739 | ||
@@ -690,9 +743,8 @@ static l_obj propagateall (global_State *g) { | |||
690 | ** inverts the direction of the traversals, trying to speed up | 743 | ** inverts the direction of the traversals, trying to speed up |
691 | ** convergence on chains in the same table. | 744 | ** convergence on chains in the same table. |
692 | */ | 745 | */ |
693 | static l_obj convergeephemerons (global_State *g) { | 746 | static void convergeephemerons (global_State *g) { |
694 | int changed; | 747 | int changed; |
695 | l_obj work = 0; | ||
696 | int dir = 0; | 748 | int dir = 0; |
697 | do { | 749 | do { |
698 | GCObject *w; | 750 | GCObject *w; |
@@ -707,11 +759,9 @@ static l_obj convergeephemerons (global_State *g) { | |||
707 | propagateall(g); /* propagate changes */ | 759 | propagateall(g); /* propagate changes */ |
708 | changed = 1; /* will have to revisit all ephemeron tables */ | 760 | changed = 1; /* will have to revisit all ephemeron tables */ |
709 | } | 761 | } |
710 | work++; | ||
711 | } | 762 | } |
712 | dir = !dir; /* invert direction next time */ | 763 | dir = !dir; /* invert direction next time */ |
713 | } while (changed); /* repeat until no more changes */ | 764 | } while (changed); /* repeat until no more changes */ |
714 | return work; | ||
715 | } | 765 | } |
716 | 766 | ||
717 | /* }====================================================== */ | 767 | /* }====================================================== */ |
@@ -727,8 +777,7 @@ static l_obj convergeephemerons (global_State *g) { | |||
727 | /* | 777 | /* |
728 | ** clear entries with unmarked keys from all weaktables in list 'l' | 778 | ** clear entries with unmarked keys from all weaktables in list 'l' |
729 | */ | 779 | */ |
730 | static l_obj clearbykeys (global_State *g, GCObject *l) { | 780 | static void clearbykeys (global_State *g, GCObject *l) { |
731 | l_obj work = 0; | ||
732 | for (; l; l = gco2t(l)->gclist) { | 781 | for (; l; l = gco2t(l)->gclist) { |
733 | Table *h = gco2t(l); | 782 | Table *h = gco2t(l); |
734 | Node *limit = gnodelast(h); | 783 | Node *limit = gnodelast(h); |
@@ -739,9 +788,7 @@ static l_obj clearbykeys (global_State *g, GCObject *l) { | |||
739 | if (isempty(gval(n))) /* is entry empty? */ | 788 | if (isempty(gval(n))) /* is entry empty? */ |
740 | clearkey(n); /* clear its key */ | 789 | clearkey(n); /* clear its key */ |
741 | } | 790 | } |
742 | work++; | ||
743 | } | 791 | } |
744 | return work; | ||
745 | } | 792 | } |
746 | 793 | ||
747 | 794 | ||
@@ -749,8 +796,7 @@ static l_obj clearbykeys (global_State *g, GCObject *l) { | |||
749 | ** clear entries with unmarked values from all weaktables in list 'l' up | 796 | ** clear entries with unmarked values from all weaktables in list 'l' up |
750 | ** to element 'f' | 797 | ** to element 'f' |
751 | */ | 798 | */ |
752 | static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) { | 799 | static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { |
753 | l_obj work = 0; | ||
754 | for (; l != f; l = gco2t(l)->gclist) { | 800 | for (; l != f; l = gco2t(l)->gclist) { |
755 | Table *h = gco2t(l); | 801 | Table *h = gco2t(l); |
756 | Node *n, *limit = gnodelast(h); | 802 | Node *n, *limit = gnodelast(h); |
@@ -767,9 +813,7 @@ static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) { | |||
767 | if (isempty(gval(n))) /* is entry empty? */ | 813 | if (isempty(gval(n))) /* is entry empty? */ |
768 | clearkey(n); /* clear its key */ | 814 | clearkey(n); /* clear its key */ |
769 | } | 815 | } |
770 | work++; | ||
771 | } | 816 | } |
772 | return work; | ||
773 | } | 817 | } |
774 | 818 | ||
775 | 819 | ||
@@ -781,7 +825,6 @@ static void freeupval (lua_State *L, UpVal *uv) { | |||
781 | 825 | ||
782 | 826 | ||
783 | static void freeobj (lua_State *L, GCObject *o) { | 827 | static void freeobj (lua_State *L, GCObject *o) { |
784 | G(L)->GCtotalobjs--; | ||
785 | switch (o->tt) { | 828 | switch (o->tt) { |
786 | case LUA_VPROTO: | 829 | case LUA_VPROTO: |
787 | luaF_freeproto(L, gco2p(o)); | 830 | luaF_freeproto(L, gco2p(o)); |
@@ -835,12 +878,11 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
835 | ** for next collection cycle. Return where to continue the traversal or | 878 | ** for next collection cycle. Return where to continue the traversal or |
836 | ** NULL if list is finished. | 879 | ** NULL if list is finished. |
837 | */ | 880 | */ |
838 | static GCObject **sweeplist (lua_State *L, GCObject **p, l_obj countin) { | 881 | static GCObject **sweeplist (lua_State *L, GCObject **p, l_mem countin) { |
839 | global_State *g = G(L); | 882 | global_State *g = G(L); |
840 | int ow = otherwhite(g); | 883 | int ow = otherwhite(g); |
841 | l_obj i; | ||
842 | int white = luaC_white(g); /* current white */ | 884 | int white = luaC_white(g); /* current white */ |
843 | for (i = 0; *p != NULL && i < countin; i++) { | 885 | while (*p != NULL && countin-- > 0) { |
844 | GCObject *curr = *p; | 886 | GCObject *curr = *p; |
845 | int marked = curr->marked; | 887 | int marked = curr->marked; |
846 | if (isdeadm(ow, marked)) { /* is 'curr' dead? */ | 888 | if (isdeadm(ow, marked)) { /* is 'curr' dead? */ |
@@ -1052,8 +1094,8 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
1052 | ** approximately (marked * pause / 100). | 1094 | ** approximately (marked * pause / 100). |
1053 | */ | 1095 | */ |
1054 | static void setpause (global_State *g) { | 1096 | static void setpause (global_State *g) { |
1055 | l_obj threshold = applygcparam(g, PAUSE, g->GCmarked); | 1097 | l_mem threshold = applygcparam(g, PAUSE, g->GCmarked); |
1056 | l_obj debt = threshold - gettotalobjs(g); | 1098 | l_mem debt = threshold - gettotalbytes(g); |
1057 | if (debt < 0) debt = 0; | 1099 | if (debt < 0) debt = 0; |
1058 | luaE_setdebt(g, debt); | 1100 | luaE_setdebt(g, debt); |
1059 | } | 1101 | } |
@@ -1103,7 +1145,7 @@ static void sweep2old (lua_State *L, GCObject **p) { | |||
1103 | */ | 1145 | */ |
1104 | static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, | 1146 | static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, |
1105 | GCObject *limit, GCObject **pfirstold1, | 1147 | GCObject *limit, GCObject **pfirstold1, |
1106 | l_obj *paddedold) { | 1148 | l_mem *paddedold) { |
1107 | static const lu_byte nextage[] = { | 1149 | static const lu_byte nextage[] = { |
1108 | G_SURVIVAL, /* from G_NEW */ | 1150 | G_SURVIVAL, /* from G_NEW */ |
1109 | G_OLD1, /* from G_SURVIVAL */ | 1151 | G_OLD1, /* from G_SURVIVAL */ |
@@ -1113,7 +1155,7 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, | |||
1113 | G_TOUCHED1, /* from G_TOUCHED1 (do not change) */ | 1155 | G_TOUCHED1, /* from G_TOUCHED1 (do not change) */ |
1114 | G_TOUCHED2 /* from G_TOUCHED2 (do not change) */ | 1156 | G_TOUCHED2 /* from G_TOUCHED2 (do not change) */ |
1115 | }; | 1157 | }; |
1116 | l_obj addedold = 0; | 1158 | l_mem addedold = 0; |
1117 | int white = luaC_white(g); | 1159 | int white = luaC_white(g); |
1118 | GCObject *curr; | 1160 | GCObject *curr; |
1119 | while ((curr = *p) != limit) { | 1161 | while ((curr = *p) != limit) { |
@@ -1132,7 +1174,7 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, | |||
1132 | lua_assert(age != G_OLD1); /* advanced in 'markold' */ | 1174 | lua_assert(age != G_OLD1); /* advanced in 'markold' */ |
1133 | setage(curr, nextage[age]); | 1175 | setage(curr, nextage[age]); |
1134 | if (getage(curr) == G_OLD1) { | 1176 | if (getage(curr) == G_OLD1) { |
1135 | addedold++; /* one more object becoming old */ | 1177 | addedold += cast(l_mem, objsize(curr)); /* bytes becoming old */ |
1136 | if (*pfirstold1 == NULL) | 1178 | if (*pfirstold1 == NULL) |
1137 | *pfirstold1 = curr; /* first OLD1 object in the list */ | 1179 | *pfirstold1 = curr; /* first OLD1 object in the list */ |
1138 | } | 1180 | } |
@@ -1257,9 +1299,9 @@ static void minor2inc (lua_State *L, global_State *g, lu_byte kind) { | |||
1257 | ** than 'minormajor'% of the number of lived objects after the last | 1299 | ** than 'minormajor'% of the number of lived objects after the last |
1258 | ** major collection. (That percentage is computed in 'limit'.) | 1300 | ** major collection. (That percentage is computed in 'limit'.) |
1259 | */ | 1301 | */ |
1260 | static int checkminormajor (global_State *g, l_obj addedold1) { | 1302 | static int checkminormajor (global_State *g, l_mem addedold1) { |
1261 | l_obj step = applygcparam(g, MINORMUL, g->GCmajorminor); | 1303 | l_mem step = applygcparam(g, MINORMUL, g->GCmajorminor); |
1262 | l_obj limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); | 1304 | l_mem limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); |
1263 | return (addedold1 >= (step >> 1) || g->GCmarked >= limit); | 1305 | return (addedold1 >= (step >> 1) || g->GCmarked >= limit); |
1264 | } | 1306 | } |
1265 | 1307 | ||
@@ -1269,8 +1311,8 @@ static int checkminormajor (global_State *g, l_obj addedold1) { | |||
1269 | ** sweep all lists and advance pointers. Finally, finish the collection. | 1311 | ** sweep all lists and advance pointers. Finally, finish the collection. |
1270 | */ | 1312 | */ |
1271 | static void youngcollection (lua_State *L, global_State *g) { | 1313 | static void youngcollection (lua_State *L, global_State *g) { |
1272 | l_obj addedold1 = 0; | 1314 | l_mem addedold1 = 0; |
1273 | l_obj marked = g->GCmarked; /* preserve 'g->GCmarked' */ | 1315 | l_mem marked = g->GCmarked; /* preserve 'g->GCmarked' */ |
1274 | GCObject **psurvival; /* to point to first non-dead survival object */ | 1316 | GCObject **psurvival; /* to point to first non-dead survival object */ |
1275 | GCObject *dummy; /* dummy out parameter to 'sweepgen' */ | 1317 | GCObject *dummy; /* dummy out parameter to 'sweepgen' */ |
1276 | lua_assert(g->gcstate == GCSpropagate); | 1318 | lua_assert(g->gcstate == GCSpropagate); |
@@ -1346,7 +1388,9 @@ static void atomic2gen (lua_State *L, global_State *g) { | |||
1346 | 1388 | ||
1347 | /* | 1389 | /* |
1348 | ** Set debt for the next minor collection, which will happen when | 1390 | ** Set debt for the next minor collection, which will happen when |
1349 | ** total number of objects grows 'genminormul'%. | 1391 | ** total number of bytes grows 'genminormul'% in relation to |
1392 | ** the base, GCmajorminor, which is the number of bytes being used | ||
1393 | ** after the last major collection. | ||
1350 | */ | 1394 | */ |
1351 | static void setminordebt (global_State *g) { | 1395 | static void setminordebt (global_State *g) { |
1352 | luaE_setdebt(g, applygcparam(g, MINORMUL, g->GCmajorminor)); | 1396 | luaE_setdebt(g, applygcparam(g, MINORMUL, g->GCmajorminor)); |
@@ -1404,18 +1448,18 @@ static void fullgen (lua_State *L, global_State *g) { | |||
1404 | */ | 1448 | */ |
1405 | static int checkmajorminor (lua_State *L, global_State *g) { | 1449 | static int checkmajorminor (lua_State *L, global_State *g) { |
1406 | if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ | 1450 | if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ |
1407 | l_obj numobjs = gettotalobjs(g); | 1451 | l_mem numbytes = gettotalbytes(g); |
1408 | l_obj addedobjs = numobjs - g->GCmajorminor; | 1452 | l_mem addedobjs = numbytes - g->GCmajorminor; |
1409 | l_obj limit = applygcparam(g, MAJORMINOR, addedobjs); | 1453 | l_mem limit = applygcparam(g, MAJORMINOR, addedobjs); |
1410 | l_obj tobecollected = numobjs - g->GCmarked; | 1454 | l_mem tobecollected = numbytes - g->GCmarked; |
1411 | if (tobecollected > limit) { | 1455 | if (tobecollected > limit) { |
1412 | atomic2gen(L, g); /* return to generational mode */ | 1456 | atomic2gen(L, g); /* return to generational mode */ |
1413 | setminordebt(g); | 1457 | setminordebt(g); |
1414 | return 0; /* exit incremental collection */ | 1458 | return 1; /* exit incremental collection */ |
1415 | } | 1459 | } |
1416 | } | 1460 | } |
1417 | g->GCmajorminor = g->GCmarked; /* prepare for next collection */ | 1461 | g->GCmajorminor = g->GCmarked; /* prepare for next collection */ |
1418 | return 1; /* stay doing incremental collections */ | 1462 | return 0; /* stay doing incremental collections */ |
1419 | } | 1463 | } |
1420 | 1464 | ||
1421 | /* }====================================================== */ | 1465 | /* }====================================================== */ |
@@ -1474,8 +1518,7 @@ void luaC_freeallobjects (lua_State *L) { | |||
1474 | } | 1518 | } |
1475 | 1519 | ||
1476 | 1520 | ||
1477 | static l_obj atomic (lua_State *L) { | 1521 | static void atomic (lua_State *L) { |
1478 | l_obj work = 0; | ||
1479 | global_State *g = G(L); | 1522 | global_State *g = G(L); |
1480 | GCObject *origweak, *origall; | 1523 | GCObject *origweak, *origall; |
1481 | GCObject *grayagain = g->grayagain; /* save original list */ | 1524 | GCObject *grayagain = g->grayagain; /* save original list */ |
@@ -1487,33 +1530,32 @@ static l_obj atomic (lua_State *L) { | |||
1487 | /* registry and global metatables may be changed by API */ | 1530 | /* registry and global metatables may be changed by API */ |
1488 | markvalue(g, &g->l_registry); | 1531 | markvalue(g, &g->l_registry); |
1489 | markmt(g); /* mark global metatables */ | 1532 | markmt(g); /* mark global metatables */ |
1490 | work += propagateall(g); /* empties 'gray' list */ | 1533 | propagateall(g); /* empties 'gray' list */ |
1491 | /* remark occasional upvalues of (maybe) dead threads */ | 1534 | /* remark occasional upvalues of (maybe) dead threads */ |
1492 | work += remarkupvals(g); | 1535 | remarkupvals(g); |
1493 | work += propagateall(g); /* propagate changes */ | 1536 | propagateall(g); /* propagate changes */ |
1494 | g->gray = grayagain; | 1537 | g->gray = grayagain; |
1495 | work += propagateall(g); /* traverse 'grayagain' list */ | 1538 | propagateall(g); /* traverse 'grayagain' list */ |
1496 | work += convergeephemerons(g); | 1539 | convergeephemerons(g); |
1497 | /* at this point, all strongly accessible objects are marked. */ | 1540 | /* at this point, all strongly accessible objects are marked. */ |
1498 | /* Clear values from weak tables, before checking finalizers */ | 1541 | /* Clear values from weak tables, before checking finalizers */ |
1499 | work += clearbyvalues(g, g->weak, NULL); | 1542 | clearbyvalues(g, g->weak, NULL); |
1500 | work += clearbyvalues(g, g->allweak, NULL); | 1543 | clearbyvalues(g, g->allweak, NULL); |
1501 | origweak = g->weak; origall = g->allweak; | 1544 | origweak = g->weak; origall = g->allweak; |
1502 | separatetobefnz(g, 0); /* separate objects to be finalized */ | 1545 | separatetobefnz(g, 0); /* separate objects to be finalized */ |
1503 | work += markbeingfnz(g); /* mark objects that will be finalized */ | 1546 | markbeingfnz(g); /* mark objects that will be finalized */ |
1504 | work += propagateall(g); /* remark, to propagate 'resurrection' */ | 1547 | propagateall(g); /* remark, to propagate 'resurrection' */ |
1505 | work += convergeephemerons(g); | 1548 | convergeephemerons(g); |
1506 | /* at this point, all resurrected objects are marked. */ | 1549 | /* at this point, all resurrected objects are marked. */ |
1507 | /* remove dead objects from weak tables */ | 1550 | /* remove dead objects from weak tables */ |
1508 | work += clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */ | 1551 | clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */ |
1509 | work += clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */ | 1552 | clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */ |
1510 | /* clear values from resurrected weak tables */ | 1553 | /* clear values from resurrected weak tables */ |
1511 | work += clearbyvalues(g, g->weak, origweak); | 1554 | clearbyvalues(g, g->weak, origweak); |
1512 | work += clearbyvalues(g, g->allweak, origall); | 1555 | clearbyvalues(g, g->allweak, origall); |
1513 | luaS_clearcache(g); | 1556 | luaS_clearcache(g); |
1514 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 1557 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
1515 | lua_assert(g->gray == NULL); | 1558 | lua_assert(g->gray == NULL); |
1516 | return work; | ||
1517 | } | 1559 | } |
1518 | 1560 | ||
1519 | 1561 | ||
@@ -1524,7 +1566,7 @@ static l_obj atomic (lua_State *L) { | |||
1524 | static void sweepstep (lua_State *L, global_State *g, | 1566 | static void sweepstep (lua_State *L, global_State *g, |
1525 | lu_byte nextstate, GCObject **nextlist, int fast) { | 1567 | lu_byte nextstate, GCObject **nextlist, int fast) { |
1526 | if (g->sweepgc) | 1568 | if (g->sweepgc) |
1527 | g->sweepgc = sweeplist(L, g->sweepgc, fast ? MAX_LOBJ : GCSWEEPMAX); | 1569 | g->sweepgc = sweeplist(L, g->sweepgc, fast ? MAX_LMEM : GCSWEEPMAX); |
1528 | else { /* enter next state */ | 1570 | else { /* enter next state */ |
1529 | g->gcstate = nextstate; | 1571 | g->gcstate = nextstate; |
1530 | g->sweepgc = nextlist; | 1572 | g->sweepgc = nextlist; |
@@ -1544,72 +1586,80 @@ static void sweepstep (lua_State *L, global_State *g, | |||
1544 | ** That avoids traversing twice some objects, such as threads and | 1586 | ** That avoids traversing twice some objects, such as threads and |
1545 | ** weak tables. | 1587 | ** weak tables. |
1546 | */ | 1588 | */ |
1547 | static l_obj singlestep (lua_State *L, int fast) { | 1589 | |
1590 | #define step2pause -3 /* finished collection; entered pause state */ | ||
1591 | #define atomicstep -2 /* atomic step */ | ||
1592 | #define step2minor -1 /* moved to minor collections */ | ||
1593 | |||
1594 | |||
1595 | static l_mem singlestep (lua_State *L, int fast) { | ||
1548 | global_State *g = G(L); | 1596 | global_State *g = G(L); |
1549 | l_obj work; | 1597 | l_mem stepresult; |
1550 | lua_assert(!g->gcstopem); /* collector is not reentrant */ | 1598 | lua_assert(!g->gcstopem); /* collector is not reentrant */ |
1551 | g->gcstopem = 1; /* no emergency collections while collecting */ | 1599 | g->gcstopem = 1; /* no emergency collections while collecting */ |
1552 | switch (g->gcstate) { | 1600 | switch (g->gcstate) { |
1553 | case GCSpause: { | 1601 | case GCSpause: { |
1554 | restartcollection(g); | 1602 | restartcollection(g); |
1555 | g->gcstate = GCSpropagate; | 1603 | g->gcstate = GCSpropagate; |
1556 | work = 1; | 1604 | stepresult = 1; |
1557 | break; | 1605 | break; |
1558 | } | 1606 | } |
1559 | case GCSpropagate: { | 1607 | case GCSpropagate: { |
1560 | if (fast || g->gray == NULL) { | 1608 | if (fast || g->gray == NULL) { |
1561 | g->gcstate = GCSenteratomic; /* finish propagate phase */ | 1609 | g->gcstate = GCSenteratomic; /* finish propagate phase */ |
1562 | work = 0; | 1610 | stepresult = 1; |
1563 | } | ||
1564 | else { | ||
1565 | propagatemark(g); /* traverse one gray object */ | ||
1566 | work = 1; | ||
1567 | } | 1611 | } |
1612 | else | ||
1613 | stepresult = propagatemark(g); /* traverse one gray object */ | ||
1568 | break; | 1614 | break; |
1569 | } | 1615 | } |
1570 | case GCSenteratomic: { | 1616 | case GCSenteratomic: { |
1571 | work = atomic(L); | 1617 | atomic(L); |
1572 | if (checkmajorminor(L, g)) | 1618 | if (checkmajorminor(L, g)) |
1619 | stepresult = step2minor; | ||
1620 | else { | ||
1573 | entersweep(L); | 1621 | entersweep(L); |
1622 | stepresult = atomicstep; | ||
1623 | } | ||
1574 | break; | 1624 | break; |
1575 | } | 1625 | } |
1576 | case GCSswpallgc: { /* sweep "regular" objects */ | 1626 | case GCSswpallgc: { /* sweep "regular" objects */ |
1577 | sweepstep(L, g, GCSswpfinobj, &g->finobj, fast); | 1627 | sweepstep(L, g, GCSswpfinobj, &g->finobj, fast); |
1578 | work = GCSWEEPMAX; | 1628 | stepresult = GCSWEEPMAX; |
1579 | break; | 1629 | break; |
1580 | } | 1630 | } |
1581 | case GCSswpfinobj: { /* sweep objects with finalizers */ | 1631 | case GCSswpfinobj: { /* sweep objects with finalizers */ |
1582 | sweepstep(L, g, GCSswptobefnz, &g->tobefnz, fast); | 1632 | sweepstep(L, g, GCSswptobefnz, &g->tobefnz, fast); |
1583 | work = GCSWEEPMAX; | 1633 | stepresult = GCSWEEPMAX; |
1584 | break; | 1634 | break; |
1585 | } | 1635 | } |
1586 | case GCSswptobefnz: { /* sweep objects to be finalized */ | 1636 | case GCSswptobefnz: { /* sweep objects to be finalized */ |
1587 | sweepstep(L, g, GCSswpend, NULL, fast); | 1637 | sweepstep(L, g, GCSswpend, NULL, fast); |
1588 | work = GCSWEEPMAX; | 1638 | stepresult = GCSWEEPMAX; |
1589 | break; | 1639 | break; |
1590 | } | 1640 | } |
1591 | case GCSswpend: { /* finish sweeps */ | 1641 | case GCSswpend: { /* finish sweeps */ |
1592 | checkSizes(L, g); | 1642 | checkSizes(L, g); |
1593 | g->gcstate = GCScallfin; | 1643 | g->gcstate = GCScallfin; |
1594 | work = 0; | 1644 | stepresult = GCSWEEPMAX; |
1595 | break; | 1645 | break; |
1596 | } | 1646 | } |
1597 | case GCScallfin: { /* call finalizers */ | 1647 | case GCScallfin: { /* call finalizers */ |
1598 | if (g->tobefnz && !g->gcemergency) { | 1648 | if (g->tobefnz && !g->gcemergency) { |
1599 | g->gcstopem = 0; /* ok collections during finalizers */ | 1649 | g->gcstopem = 0; /* ok collections during finalizers */ |
1600 | GCTM(L); /* call one finalizer */ | 1650 | GCTM(L); /* call one finalizer */ |
1601 | work = 1; | 1651 | stepresult = CWUFIN; |
1602 | } | 1652 | } |
1603 | else { /* emergency mode or no more finalizers */ | 1653 | else { /* emergency mode or no more finalizers */ |
1604 | g->gcstate = GCSpause; /* finish collection */ | 1654 | g->gcstate = GCSpause; /* finish collection */ |
1605 | work = 0; | 1655 | stepresult = step2pause; |
1606 | } | 1656 | } |
1607 | break; | 1657 | break; |
1608 | } | 1658 | } |
1609 | default: lua_assert(0); return 0; | 1659 | default: lua_assert(0); return 0; |
1610 | } | 1660 | } |
1611 | g->gcstopem = 0; | 1661 | g->gcstopem = 0; |
1612 | return work; | 1662 | return stepresult; |
1613 | } | 1663 | } |
1614 | 1664 | ||
1615 | 1665 | ||
@@ -1635,25 +1685,26 @@ void luaC_runtilstate (lua_State *L, int state, int fast) { | |||
1635 | ** controls when next step will be performed. | 1685 | ** controls when next step will be performed. |
1636 | */ | 1686 | */ |
1637 | static void incstep (lua_State *L, global_State *g) { | 1687 | static void incstep (lua_State *L, global_State *g) { |
1638 | l_obj stepsize = applygcparam(g, STEPSIZE, 100); | 1688 | l_mem stepsize = applygcparam(g, STEPSIZE, 100); |
1639 | l_obj work2do = applygcparam(g, STEPMUL, stepsize); | 1689 | l_mem work2do = applygcparam(g, STEPMUL, stepsize); |
1640 | int fast = 0; | 1690 | l_mem stres; |
1641 | if (work2do == 0) { /* special case: do a full collection */ | 1691 | int fast = (work2do == 0); /* special case: do a full collection */ |
1642 | work2do = MAX_LOBJ; /* do unlimited work */ | 1692 | do { /* repeat until enough work */ |
1643 | fast = 1; | 1693 | stres = singlestep(L, fast); /* perform one single step */ |
1644 | } | 1694 | if (stres == step2minor) /* returned to minor collections? */ |
1645 | do { /* repeat until pause or enough work */ | ||
1646 | l_obj work = singlestep(L, fast); /* perform one single step */ | ||
1647 | if (g->gckind == KGC_GENMINOR) /* returned to minor collections? */ | ||
1648 | return; /* nothing else to be done here */ | 1695 | return; /* nothing else to be done here */ |
1649 | work2do -= work; | 1696 | else if (stres == step2pause || (stres == atomicstep && !fast)) |
1650 | } while (work2do > 0 && g->gcstate != GCSpause); | 1697 | break; /* end of cycle or atomic */ |
1698 | else | ||
1699 | work2do -= stres; | ||
1700 | } while (fast || work2do > 0); | ||
1651 | if (g->gcstate == GCSpause) | 1701 | if (g->gcstate == GCSpause) |
1652 | setpause(g); /* pause until next cycle */ | 1702 | setpause(g); /* pause until next cycle */ |
1653 | else | 1703 | else |
1654 | luaE_setdebt(g, stepsize); | 1704 | luaE_setdebt(g, stepsize); |
1655 | } | 1705 | } |
1656 | 1706 | ||
1707 | |||
1657 | /* | 1708 | /* |
1658 | ** Performs a basic GC step if collector is running. (If collector is | 1709 | ** Performs a basic GC step if collector is running. (If collector is |
1659 | ** not running, set a reasonable debt to avoid it being called at | 1710 | ** not running, set a reasonable debt to avoid it being called at |
@@ -1663,17 +1714,23 @@ void luaC_step (lua_State *L) { | |||
1663 | global_State *g = G(L); | 1714 | global_State *g = G(L); |
1664 | lua_assert(!g->gcemergency); | 1715 | lua_assert(!g->gcemergency); |
1665 | if (!gcrunning(g)) /* not running? */ | 1716 | if (!gcrunning(g)) /* not running? */ |
1666 | luaE_setdebt(g, 2000); | 1717 | luaE_setdebt(g, 20000); |
1667 | else { | 1718 | else { |
1719 | // printf("mem: %ld kind: %s ", gettotalbytes(g), | ||
1720 | // g->gckind == KGC_INC ? "inc" : g->gckind == KGC_GENMAJOR ? "genmajor" : | ||
1721 | // "genminor"); | ||
1668 | switch (g->gckind) { | 1722 | switch (g->gckind) { |
1669 | case KGC_INC: case KGC_GENMAJOR: | 1723 | case KGC_INC: case KGC_GENMAJOR: |
1724 | // printf("(%d -> ", g->gcstate); | ||
1670 | incstep(L, g); | 1725 | incstep(L, g); |
1726 | // printf("%d) ", g->gcstate); | ||
1671 | break; | 1727 | break; |
1672 | case KGC_GENMINOR: | 1728 | case KGC_GENMINOR: |
1673 | youngcollection(L, g); | 1729 | youngcollection(L, g); |
1674 | setminordebt(g); | 1730 | setminordebt(g); |
1675 | break; | 1731 | break; |
1676 | } | 1732 | } |
1733 | // printf("-> mem: %ld debt: %ld\n", gettotalbytes(g), g->GCdebt); | ||
1677 | } | 1734 | } |
1678 | } | 1735 | } |
1679 | 1736 | ||
@@ -1692,7 +1749,7 @@ static void fullinc (lua_State *L, global_State *g) { | |||
1692 | luaC_runtilstate(L, GCSpause, 1); | 1749 | luaC_runtilstate(L, GCSpause, 1); |
1693 | luaC_runtilstate(L, GCScallfin, 1); /* run up to finalizers */ | 1750 | luaC_runtilstate(L, GCScallfin, 1); /* run up to finalizers */ |
1694 | /* 'marked' must be correct after a full GC cycle */ | 1751 | /* 'marked' must be correct after a full GC cycle */ |
1695 | lua_assert(g->GCmarked == gettotalobjs(g)); | 1752 | /* lua_assert(g->GCmarked == gettotalobjs(g)); ??? */ |
1696 | luaC_runtilstate(L, GCSpause, 1); /* finish collection */ | 1753 | luaC_runtilstate(L, GCSpause, 1); /* finish collection */ |
1697 | setpause(g); | 1754 | setpause(g); |
1698 | } | 1755 | } |