aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c417
1 files changed, 177 insertions, 240 deletions
diff --git a/lgc.c b/lgc.c
index a3094ff5..27856650 100644
--- a/lgc.c
+++ b/lgc.c
@@ -19,6 +19,7 @@
19#include "ldo.h" 19#include "ldo.h"
20#include "lfunc.h" 20#include "lfunc.h"
21#include "lgc.h" 21#include "lgc.h"
22#include "llex.h"
22#include "lmem.h" 23#include "lmem.h"
23#include "lobject.h" 24#include "lobject.h"
24#include "lstate.h" 25#include "lstate.h"
@@ -28,36 +29,18 @@
28 29
29 30
30/* 31/*
31** Maximum number of elements to sweep in each single step. 32** Number of fixed (luaC_fix) objects in a Lua state: metafield names,
32** (Large enough to dissipate fixed overheads but small enough 33** plus reserved words, plus "_ENV", plus the memory-error message.
33** to allow small steps for the collector.)
34*/
35#define GCSWEEPMAX 100
36
37/*
38** Maximum number of finalizers to call in each single step.
39*/
40#define GCFINMAX 10
41
42
43/*
44** Cost of calling one finalizer.
45*/
46#define GCFINALIZECOST 50
47
48
49/*
50** The equivalent, in bytes, of one unit of "work" (visiting a slot,
51** sweeping an object, etc.)
52*/ 34*/
53#define WORK2MEM sizeof(TValue) 35#define NFIXED (TM_N + NUM_RESERVED + 2)
54 36
55 37
56/* 38/*
57** macro to adjust 'pause': 'pause' is actually used like 39** Maximum number of elements to sweep in each single step.
58** 'pause / PAUSEADJ' (value chosen by tests) 40** (Large enough to dissipate fixed overheads but small enough
41** to allow small steps for the collector.)
59*/ 42*/
60#define PAUSEADJ 100 43#define GCSWEEPMAX 20
61 44
62 45
63/* mask with all color bits */ 46/* mask with all color bits */
@@ -105,7 +88,7 @@
105#define markobjectN(g,t) { if (t) markobject(g,t); } 88#define markobjectN(g,t) { if (t) markobject(g,t); }
106 89
107static void reallymarkobject (global_State *g, GCObject *o); 90static void reallymarkobject (global_State *g, GCObject *o);
108static lu_mem atomic (lua_State *L); 91static l_obj atomic (lua_State *L);
109static void entersweep (lua_State *L); 92static void entersweep (lua_State *L);
110 93
111 94
@@ -217,7 +200,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
217 } 200 }
218 else { /* sweep phase */ 201 else { /* sweep phase */
219 lua_assert(issweepphase(g)); 202 lua_assert(issweepphase(g));
220 if (g->gckind == KGC_INC) /* incremental mode? */ 203 if (g->gckind != KGC_GEN) /* incremental mode? */
221 makewhite(g, o); /* mark 'o' as white to avoid other barriers */ 204 makewhite(g, o); /* mark 'o' as white to avoid other barriers */
222 } 205 }
223} 206}
@@ -259,6 +242,7 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
259 global_State *g = G(L); 242 global_State *g = G(L);
260 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); 243 char *p = cast_charp(luaM_newobject(L, novariant(tt), sz));
261 GCObject *o = cast(GCObject *, p + offset); 244 GCObject *o = cast(GCObject *, p + offset);
245 g->GCdebt--;
262 o->marked = luaC_white(g); 246 o->marked = luaC_white(g);
263 o->tt = tt; 247 o->tt = tt;
264 o->next = g->allgc; 248 o->next = g->allgc;
@@ -267,6 +251,9 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) {
267} 251}
268 252
269 253
254/*
255** create a new collectable object with no offset.
256*/
270GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { 257GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
271 return luaC_newobjdt(L, tt, sz, 0); 258 return luaC_newobjdt(L, tt, sz, 0);
272} 259}
@@ -295,6 +282,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
295** (only closures can), and a userdata's metatable must be a table. 282** (only closures can), and a userdata's metatable must be a table.
296*/ 283*/
297static void reallymarkobject (global_State *g, GCObject *o) { 284static void reallymarkobject (global_State *g, GCObject *o) {
285 g->marked++;
298 switch (o->tt) { 286 switch (o->tt) {
299 case LUA_VSHRSTR: 287 case LUA_VSHRSTR:
300 case LUA_VLNGSTR: { 288 case LUA_VLNGSTR: {
@@ -342,9 +330,9 @@ static void markmt (global_State *g) {
342/* 330/*
343** mark all objects in list of being-finalized 331** mark all objects in list of being-finalized
344*/ 332*/
345static lu_mem markbeingfnz (global_State *g) { 333static l_obj markbeingfnz (global_State *g) {
346 GCObject *o; 334 GCObject *o;
347 lu_mem count = 0; 335 l_obj count = 0;
348 for (o = g->tobefnz; o != NULL; o = o->next) { 336 for (o = g->tobefnz; o != NULL; o = o->next) {
349 count++; 337 count++;
350 markobject(g, o); 338 markobject(g, o);
@@ -364,12 +352,11 @@ static lu_mem markbeingfnz (global_State *g) {
364** upvalues, as they have nothing to be checked. (If the thread gets an 352** upvalues, as they have nothing to be checked. (If the thread gets an
365** upvalue later, it will be linked in the list again.) 353** upvalue later, it will be linked in the list again.)
366*/ 354*/
367static int remarkupvals (global_State *g) { 355static l_obj remarkupvals (global_State *g) {
356 l_obj work = 0;
368 lua_State *thread; 357 lua_State *thread;
369 lua_State **p = &g->twups; 358 lua_State **p = &g->twups;
370 int work = 0; /* estimate of how much work was done here */
371 while ((thread = *p) != NULL) { 359 while ((thread = *p) != NULL) {
372 work++;
373 if (!iswhite(thread) && thread->openupval != NULL) 360 if (!iswhite(thread) && thread->openupval != NULL)
374 p = &thread->twups; /* keep marked thread with upvalues in the list */ 361 p = &thread->twups; /* keep marked thread with upvalues in the list */
375 else { /* thread is not marked or without upvalues */ 362 else { /* thread is not marked or without upvalues */
@@ -379,13 +366,13 @@ static int remarkupvals (global_State *g) {
379 thread->twups = thread; /* mark that it is out of list */ 366 thread->twups = thread; /* mark that it is out of list */
380 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { 367 for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) {
381 lua_assert(getage(uv) <= getage(thread)); 368 lua_assert(getage(uv) <= getage(thread));
382 work++;
383 if (!iswhite(uv)) { /* upvalue already visited? */ 369 if (!iswhite(uv)) { /* upvalue already visited? */
384 lua_assert(upisopen(uv) && isgray(uv)); 370 lua_assert(upisopen(uv) && isgray(uv));
385 markvalue(g, uv->v.p); /* mark its value */ 371 markvalue(g, uv->v.p); /* mark its value */
386 } 372 }
387 } 373 }
388 } 374 }
375 work++;
389 } 376 }
390 return work; 377 return work;
391} 378}
@@ -398,10 +385,15 @@ static void cleargraylists (global_State *g) {
398 385
399 386
400/* 387/*
401** mark root set and reset all gray lists, to start a new collection 388** mark root set and reset all gray lists, to start a new collection.
389** 'marked' is initialized with the number of fixed objects in the state,
390** to count the total number of live objects during a cycle. (That is
391** the metafield names, plus the reserved words, plus "_ENV" plus the
392** memory-error message.)
402*/ 393*/
403static void restartcollection (global_State *g) { 394static void restartcollection (global_State *g) {
404 cleargraylists(g); 395 cleargraylists(g);
396 g->marked = NFIXED;
405 markobject(g, g->mainthread); 397 markobject(g, g->mainthread);
406 markvalue(g, &g->l_registry); 398 markvalue(g, &g->l_registry);
407 markmt(g); 399 markmt(g);
@@ -539,7 +531,7 @@ static void traversestrongtable (global_State *g, Table *h) {
539} 531}
540 532
541 533
542static lu_mem traversetable (global_State *g, Table *h) { 534static void traversetable (global_State *g, Table *h) {
543 const char *weakkey, *weakvalue; 535 const char *weakkey, *weakvalue;
544 const TValue *mode = gfasttm(g, h->metatable, TM_MODE); 536 const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
545 markobjectN(g, h->metatable); 537 markobjectN(g, h->metatable);
@@ -556,17 +548,15 @@ static lu_mem traversetable (global_State *g, Table *h) {
556 } 548 }
557 else /* not weak */ 549 else /* not weak */
558 traversestrongtable(g, h); 550 traversestrongtable(g, h);
559 return 1 + h->alimit + 2 * allocsizenode(h);
560} 551}
561 552
562 553
563static int traverseudata (global_State *g, Udata *u) { 554static void traverseudata (global_State *g, Udata *u) {
564 int i; 555 int i;
565 markobjectN(g, u->metatable); /* mark its metatable */ 556 markobjectN(g, u->metatable); /* mark its metatable */
566 for (i = 0; i < u->nuvalue; i++) 557 for (i = 0; i < u->nuvalue; i++)
567 markvalue(g, &u->uv[i].uv); 558 markvalue(g, &u->uv[i].uv);
568 genlink(g, obj2gco(u)); 559 genlink(g, obj2gco(u));
569 return 1 + u->nuvalue;
570} 560}
571 561
572 562
@@ -575,7 +565,7 @@ static int traverseudata (global_State *g, Udata *u) {
575** arrays can be larger than needed; the extra slots are filled with 565** arrays can be larger than needed; the extra slots are filled with
576** NULL, so the use of 'markobjectN') 566** NULL, so the use of 'markobjectN')
577*/ 567*/
578static int traverseproto (global_State *g, Proto *f) { 568static void traverseproto (global_State *g, Proto *f) {
579 int i; 569 int i;
580 markobjectN(g, f->source); 570 markobjectN(g, f->source);
581 for (i = 0; i < f->sizek; i++) /* mark literals */ 571 for (i = 0; i < f->sizek; i++) /* mark literals */
@@ -586,29 +576,26 @@ static int traverseproto (global_State *g, Proto *f) {
586 markobjectN(g, f->p[i]); 576 markobjectN(g, f->p[i]);
587 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ 577 for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
588 markobjectN(g, f->locvars[i].varname); 578 markobjectN(g, f->locvars[i].varname);
589 return 1 + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
590} 579}
591 580
592 581
593static int traverseCclosure (global_State *g, CClosure *cl) { 582static void traverseCclosure (global_State *g, CClosure *cl) {
594 int i; 583 int i;
595 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ 584 for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
596 markvalue(g, &cl->upvalue[i]); 585 markvalue(g, &cl->upvalue[i]);
597 return 1 + cl->nupvalues;
598} 586}
599 587
600/* 588/*
601** Traverse a Lua closure, marking its prototype and its upvalues. 589** Traverse a Lua closure, marking its prototype and its upvalues.
602** (Both can be NULL while closure is being created.) 590** (Both can be NULL while closure is being created.)
603*/ 591*/
604static int traverseLclosure (global_State *g, LClosure *cl) { 592static void traverseLclosure (global_State *g, LClosure *cl) {
605 int i; 593 int i;
606 markobjectN(g, cl->p); /* mark its prototype */ 594 markobjectN(g, cl->p); /* mark its prototype */
607 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ 595 for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */
608 UpVal *uv = cl->upvals[i]; 596 UpVal *uv = cl->upvals[i];
609 markobjectN(g, uv); /* mark upvalue */ 597 markobjectN(g, uv); /* mark upvalue */
610 } 598 }
611 return 1 + cl->nupvalues;
612} 599}
613 600
614 601
@@ -624,13 +611,13 @@ static int traverseLclosure (global_State *g, LClosure *cl) {
624** (which can only happen in generational mode) or if the traverse is in 611** (which can only happen in generational mode) or if the traverse is in
625** the propagate phase (which can only happen in incremental mode). 612** the propagate phase (which can only happen in incremental mode).
626*/ 613*/
627static int traversethread (global_State *g, lua_State *th) { 614static void traversethread (global_State *g, lua_State *th) {
628 UpVal *uv; 615 UpVal *uv;
629 StkId o = th->stack.p; 616 StkId o = th->stack.p;
630 if (isold(th) || g->gcstate == GCSpropagate) 617 if (isold(th) || g->gcstate == GCSpropagate)
631 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ 618 linkgclist(th, g->grayagain); /* insert into 'grayagain' list */
632 if (o == NULL) 619 if (o == NULL)
633 return 1; /* stack not completely built yet */ 620 return; /* stack not completely built yet */
634 lua_assert(g->gcstate == GCSatomic || 621 lua_assert(g->gcstate == GCSatomic ||
635 th->openupval == NULL || isintwups(th)); 622 th->openupval == NULL || isintwups(th));
636 for (; o < th->top.p; o++) /* mark live elements in the stack */ 623 for (; o < th->top.p; o++) /* mark live elements in the stack */
@@ -648,34 +635,35 @@ static int traversethread (global_State *g, lua_State *th) {
648 } 635 }
649 else if (!g->gcemergency) 636 else if (!g->gcemergency)
650 luaD_shrinkstack(th); /* do not change stack in emergency cycle */ 637 luaD_shrinkstack(th); /* do not change stack in emergency cycle */
651 return 1 + stacksize(th);
652} 638}
653 639
654 640
655/* 641/*
656** traverse one gray object, turning it to black. 642** traverse one gray object, turning it to black.
657*/ 643*/
658static lu_mem propagatemark (global_State *g) { 644static void propagatemark (global_State *g) {
659 GCObject *o = g->gray; 645 GCObject *o = g->gray;
660 nw2black(o); 646 nw2black(o);
661 g->gray = *getgclist(o); /* remove from 'gray' list */ 647 g->gray = *getgclist(o); /* remove from 'gray' list */
662 switch (o->tt) { 648 switch (o->tt) {
663 case LUA_VTABLE: return traversetable(g, gco2t(o)); 649 case LUA_VTABLE: traversetable(g, gco2t(o)); break;
664 case LUA_VUSERDATA: return traverseudata(g, gco2u(o)); 650 case LUA_VUSERDATA: traverseudata(g, gco2u(o)); break;
665 case LUA_VLCL: return traverseLclosure(g, gco2lcl(o)); 651 case LUA_VLCL: traverseLclosure(g, gco2lcl(o)); break;
666 case LUA_VCCL: return traverseCclosure(g, gco2ccl(o)); 652 case LUA_VCCL: traverseCclosure(g, gco2ccl(o)); break;
667 case LUA_VPROTO: return traverseproto(g, gco2p(o)); 653 case LUA_VPROTO: traverseproto(g, gco2p(o)); break;
668 case LUA_VTHREAD: return traversethread(g, gco2th(o)); 654 case LUA_VTHREAD: traversethread(g, gco2th(o)); break;
669 default: lua_assert(0); return 0; 655 default: lua_assert(0);
670 } 656 }
671} 657}
672 658
673 659
674static lu_mem propagateall (global_State *g) { 660static l_obj propagateall (global_State *g) {
675 lu_mem tot = 0; 661 l_obj work = 0;
676 while (g->gray) 662 while (g->gray) {
677 tot += propagatemark(g); 663 propagatemark(g);
678 return tot; 664 work++;
665 }
666 return work;
679} 667}
680 668
681 669
@@ -684,10 +672,10 @@ static lu_mem propagateall (global_State *g) {
684** Repeat until it converges, that is, nothing new is marked. 'dir' 672** Repeat until it converges, that is, nothing new is marked. 'dir'
685** inverts the direction of the traversals, trying to speed up 673** inverts the direction of the traversals, trying to speed up
686** convergence on chains in the same table. 674** convergence on chains in the same table.
687**
688*/ 675*/
689static void convergeephemerons (global_State *g) { 676static l_obj convergeephemerons (global_State *g) {
690 int changed; 677 int changed;
678 l_obj work = 0;
691 int dir = 0; 679 int dir = 0;
692 do { 680 do {
693 GCObject *w; 681 GCObject *w;
@@ -702,9 +690,11 @@ static void convergeephemerons (global_State *g) {
702 propagateall(g); /* propagate changes */ 690 propagateall(g); /* propagate changes */
703 changed = 1; /* will have to revisit all ephemeron tables */ 691 changed = 1; /* will have to revisit all ephemeron tables */
704 } 692 }
693 work++;
705 } 694 }
706 dir = !dir; /* invert direction next time */ 695 dir = !dir; /* invert direction next time */
707 } while (changed); /* repeat until no more changes */ 696 } while (changed); /* repeat until no more changes */
697 return work;
708} 698}
709 699
710/* }====================================================== */ 700/* }====================================================== */
@@ -720,7 +710,8 @@ static void convergeephemerons (global_State *g) {
720/* 710/*
721** clear entries with unmarked keys from all weaktables in list 'l' 711** clear entries with unmarked keys from all weaktables in list 'l'
722*/ 712*/
723static void clearbykeys (global_State *g, GCObject *l) { 713static l_obj clearbykeys (global_State *g, GCObject *l) {
714 l_obj work = 0;
724 for (; l; l = gco2t(l)->gclist) { 715 for (; l; l = gco2t(l)->gclist) {
725 Table *h = gco2t(l); 716 Table *h = gco2t(l);
726 Node *limit = gnodelast(h); 717 Node *limit = gnodelast(h);
@@ -731,7 +722,9 @@ static void clearbykeys (global_State *g, GCObject *l) {
731 if (isempty(gval(n))) /* is entry empty? */ 722 if (isempty(gval(n))) /* is entry empty? */
732 clearkey(n); /* clear its key */ 723 clearkey(n); /* clear its key */
733 } 724 }
725 work++;
734 } 726 }
727 return work;
735} 728}
736 729
737 730
@@ -739,7 +732,8 @@ static void clearbykeys (global_State *g, GCObject *l) {
739** clear entries with unmarked values from all weaktables in list 'l' up 732** clear entries with unmarked values from all weaktables in list 'l' up
740** to element 'f' 733** to element 'f'
741*/ 734*/
742static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { 735static l_obj clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
736 l_obj work = 0;
743 for (; l != f; l = gco2t(l)->gclist) { 737 for (; l != f; l = gco2t(l)->gclist) {
744 Table *h = gco2t(l); 738 Table *h = gco2t(l);
745 Node *n, *limit = gnodelast(h); 739 Node *n, *limit = gnodelast(h);
@@ -756,7 +750,9 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
756 if (isempty(gval(n))) /* is entry empty? */ 750 if (isempty(gval(n))) /* is entry empty? */
757 clearkey(n); /* clear its key */ 751 clearkey(n); /* clear its key */
758 } 752 }
753 work++;
759 } 754 }
755 return work;
760} 756}
761 757
762 758
@@ -768,6 +764,7 @@ static void freeupval (lua_State *L, UpVal *uv) {
768 764
769 765
770static void freeobj (lua_State *L, GCObject *o) { 766static void freeobj (lua_State *L, GCObject *o) {
767 G(L)->totalobjs--;
771 switch (o->tt) { 768 switch (o->tt) {
772 case LUA_VPROTO: 769 case LUA_VPROTO:
773 luaF_freeproto(L, gco2p(o)); 770 luaF_freeproto(L, gco2p(o));
@@ -817,10 +814,9 @@ static void freeobj (lua_State *L, GCObject *o) {
817** objects, where a dead object is one marked with the old (non current) 814** objects, where a dead object is one marked with the old (non current)
818** white; change all non-dead objects back to white, preparing for next 815** white; change all non-dead objects back to white, preparing for next
819** collection cycle. Return where to continue the traversal or NULL if 816** collection cycle. Return where to continue the traversal or NULL if
820** list is finished. ('*countout' gets the number of elements traversed.) 817** list is finished.
821*/ 818*/
822static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, 819static GCObject **sweeplist (lua_State *L, GCObject **p, int countin) {
823 int *countout) {
824 global_State *g = G(L); 820 global_State *g = G(L);
825 int ow = otherwhite(g); 821 int ow = otherwhite(g);
826 int i; 822 int i;
@@ -837,8 +833,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
837 p = &curr->next; /* go to next element */ 833 p = &curr->next; /* go to next element */
838 } 834 }
839 } 835 }
840 if (countout)
841 *countout = i; /* number of elements traversed */
842 return (*p == NULL) ? NULL : p; 836 return (*p == NULL) ? NULL : p;
843} 837}
844 838
@@ -849,7 +843,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin,
849static GCObject **sweeptolive (lua_State *L, GCObject **p) { 843static GCObject **sweeptolive (lua_State *L, GCObject **p) {
850 GCObject **old = p; 844 GCObject **old = p;
851 do { 845 do {
852 p = sweeplist(L, p, 1, NULL); 846 p = sweeplist(L, p, 1);
853 } while (p == old); 847 } while (p == old);
854 return p; 848 return p;
855} 849}
@@ -868,11 +862,8 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) {
868*/ 862*/
869static void checkSizes (lua_State *L, global_State *g) { 863static void checkSizes (lua_State *L, global_State *g) {
870 if (!g->gcemergency) { 864 if (!g->gcemergency) {
871 if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ 865 if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
872 l_mem olddebt = g->GCdebt;
873 luaS_resize(L, g->strt.size / 2); 866 luaS_resize(L, g->strt.size / 2);
874 g->GCestimate += g->GCdebt - olddebt; /* correct estimate */
875 }
876 } 867 }
877} 868}
878 869
@@ -931,18 +922,6 @@ static void GCTM (lua_State *L) {
931 922
932 923
933/* 924/*
934** Call a few finalizers
935*/
936static int runafewfinalizers (lua_State *L, int n) {
937 global_State *g = G(L);
938 int i;
939 for (i = 0; i < n && g->tobefnz; i++)
940 GCTM(L); /* call one finalizer */
941 return i;
942}
943
944
945/*
946** call all pending finalizers 925** call all pending finalizers
947*/ 926*/
948static void callallpendingfinalizers (lua_State *L) { 927static void callallpendingfinalizers (lua_State *L) {
@@ -1050,20 +1029,13 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
1050 1029
1051/* 1030/*
1052** Set the "time" to wait before starting a new GC cycle; cycle will 1031** Set the "time" to wait before starting a new GC cycle; cycle will
1053** start when memory use hits the threshold of ('estimate' * pause / 1032** start when number of objects in use hits the threshold of
1054** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, 1033** approximately (marked * pause / 100).
1055** because Lua cannot even start with less than PAUSEADJ bytes).
1056*/ 1034*/
1057static void setpause (global_State *g) { 1035static void setpause (global_State *g) {
1058 l_mem threshold, debt; 1036 l_obj threshold = applygcparam(g, gcpause, g->marked);
1059 int pause = getgcparam(g->gcpause); 1037 l_obj debt = threshold - gettotalobjs(g);
1060 l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ 1038 if (debt < 0) debt = 0;
1061 lua_assert(estimate > 0);
1062 threshold = (pause < MAX_LMEM / estimate) /* overflow? */
1063 ? estimate * pause /* no overflow */
1064 : MAX_LMEM; /* overflow; truncate to maximum */
1065 debt = gettotalbytes(g) - threshold;
1066 if (debt > 0) debt = 0;
1067 luaE_setdebt(g, debt); 1039 luaE_setdebt(g, debt);
1068} 1040}
1069 1041
@@ -1303,18 +1275,17 @@ static void atomic2gen (lua_State *L, global_State *g) {
1303 sweep2old(L, &g->tobefnz); 1275 sweep2old(L, &g->tobefnz);
1304 1276
1305 g->gckind = KGC_GEN; 1277 g->gckind = KGC_GEN;
1306 g->lastatomic = 0; 1278 g->GClastmajor = gettotalobjs(g); /* base for memory control */
1307 g->GCestimate = gettotalbytes(g); /* base for memory control */
1308 finishgencycle(L, g); 1279 finishgencycle(L, g);
1309} 1280}
1310 1281
1311 1282
1312/* 1283/*
1313** Set debt for the next minor collection, which will happen when 1284** Set debt for the next minor collection, which will happen when
1314** memory grows 'genminormul'%. 1285** total number of objects grows 'genminormul'%.
1315*/ 1286*/
1316static void setminordebt (global_State *g) { 1287static void setminordebt (global_State *g) {
1317 luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); 1288 luaE_setdebt(g, applygcparam(g, genminormul, gettotalobjs(g)));
1318} 1289}
1319 1290
1320 1291
@@ -1324,14 +1295,12 @@ static void setminordebt (global_State *g) {
1324** are cleared. Then, turn all objects into old and finishes the 1295** are cleared. Then, turn all objects into old and finishes the
1325** collection. 1296** collection.
1326*/ 1297*/
1327static lu_mem entergen (lua_State *L, global_State *g) { 1298static void entergen (lua_State *L, global_State *g) {
1328 lu_mem numobjs;
1329 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ 1299 luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */
1330 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1300 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1331 numobjs = atomic(L); /* propagates all and then do the atomic stuff */ 1301 atomic(L); /* propagates all and then do the atomic stuff */
1332 atomic2gen(L, g); 1302 atomic2gen(L, g);
1333 setminordebt(g); /* set debt assuming next cycle will be minor */ 1303 setminordebt(g); /* set debt assuming next cycle will be minor */
1334 return numobjs;
1335} 1304}
1336 1305
1337 1306
@@ -1348,7 +1317,6 @@ static void enterinc (global_State *g) {
1348 g->finobjrold = g->finobjold1 = g->finobjsur = NULL; 1317 g->finobjrold = g->finobjold1 = g->finobjsur = NULL;
1349 g->gcstate = GCSpause; 1318 g->gcstate = GCSpause;
1350 g->gckind = KGC_INC; 1319 g->gckind = KGC_INC;
1351 g->lastatomic = 0;
1352} 1320}
1353 1321
1354 1322
@@ -1357,111 +1325,77 @@ static void enterinc (global_State *g) {
1357*/ 1325*/
1358void luaC_changemode (lua_State *L, int newmode) { 1326void luaC_changemode (lua_State *L, int newmode) {
1359 global_State *g = G(L); 1327 global_State *g = G(L);
1360 if (newmode != g->gckind) { 1328 if (newmode != g->gckind) { /* does it need to change? */
1361 if (newmode == KGC_GEN) /* entering generational mode? */ 1329 if (newmode == KGC_INC) { /* entering incremental mode? */
1330 if (g->gckind == KGC_GENMAJOR)
1331 g->gckind = KGC_INC; /* already incremental but in name */
1332 else
1333 enterinc(g); /* entering incremental mode */
1334 }
1335 else {
1336 lua_assert(newmode == KGC_GEN);
1362 entergen(L, g); 1337 entergen(L, g);
1363 else 1338 }
1364 enterinc(g); /* entering incremental mode */
1365 } 1339 }
1366 g->lastatomic = 0;
1367} 1340}
1368 1341
1369 1342
1370/* 1343/*
1371** Does a full collection in generational mode. 1344** Does a full collection in generational mode.
1372*/ 1345*/
1373static lu_mem fullgen (lua_State *L, global_State *g) { 1346static void fullgen (lua_State *L, global_State *g) {
1374 enterinc(g); 1347 enterinc(g);
1375 return entergen(L, g); 1348 entergen(L, g);
1376} 1349}
1377 1350
1378 1351
1379/* 1352/*
1380** Does a major collection after last collection was a "bad collection". 1353** Does a major collector up to the atomic phase and then either
1381** 1354** returns to minor collections or stays doing major ones. If the
1382** When the program is building a big structure, it allocates lots of 1355** number of objects collected this time (numobjs - marked) is more than
1383** memory but generates very little garbage. In those scenarios, 1356** half the number of objects created since the last major collection
1384** the generational mode just wastes time doing small collections, and 1357** (numobjs - lastmajor), it goes back to minor collections.
1385** major collections are frequently what we call a "bad collection", a 1358*/
1386** collection that frees too few objects. To avoid the cost of switching 1359static void genmajorstep (lua_State *L, global_State *g) {
1387** between generational mode and the incremental mode needed for full 1360 l_obj lastmajor = g->GClastmajor; /* count from last collection */
1388** (major) collections, the collector tries to stay in incremental mode 1361 l_obj numobjs = gettotalobjs(g); /* current count */
1389** after a bad collection, and to switch back to generational mode only
1390** after a "good" collection (one that traverses less than 9/8 objects
1391** of the previous one).
1392** The collector must choose whether to stay in incremental mode or to
1393** switch back to generational mode before sweeping. At this point, it
1394** does not know the real memory in use, so it cannot use memory to
1395** decide whether to return to generational mode. Instead, it uses the
1396** number of objects traversed (returned by 'atomic') as a proxy. The
1397** field 'g->lastatomic' keeps this count from the last collection.
1398** ('g->lastatomic != 0' also means that the last collection was bad.)
1399*/
1400static void stepgenfull (lua_State *L, global_State *g) {
1401 lu_mem newatomic; /* count of traversed objects */
1402 lu_mem lastatomic = g->lastatomic; /* count from last collection */
1403 if (g->gckind == KGC_GEN) /* still in generational mode? */
1404 enterinc(g); /* enter incremental mode */
1405 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ 1362 luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */
1406 newatomic = atomic(L); /* mark everybody */ 1363 atomic(L); /* mark everybody */
1407 if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ 1364 if ((numobjs - g->marked) > ((numobjs - lastmajor) >> 1)) {
1408 atomic2gen(L, g); /* return to generational mode */ 1365 atomic2gen(L, g); /* return to generational mode */
1409 setminordebt(g); 1366 setminordebt(g);
1410 } 1367 }
1411 else { /* another bad collection; stay in incremental mode */ 1368 else { /* bad collection; stay in major mode */
1412 g->GCestimate = gettotalbytes(g); /* first estimate */;
1413 entersweep(L); 1369 entersweep(L);
1414 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1370 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1415 setpause(g); 1371 setpause(g);
1416 g->lastatomic = newatomic; 1372 g->GClastmajor = gettotalobjs(g);
1417 } 1373 }
1418} 1374}
1419 1375
1420 1376
1421/* 1377/*
1422** Does a generational "step". 1378** Does a generational "step". If the total number of objects grew
1423** Usually, this means doing a minor collection and setting the debt to 1379** more than 'majormul'% since the last major collection, does a
1424** make another collection when memory grows 'genminormul'% larger. 1380** major collection. Otherwise, does a minor collection. The test
1425** 1381** ('GCdebt' != 0) avoids major collections when the step originated from
1426** However, there are exceptions. If memory grows 'genmajormul'% 1382** 'collectgarbage("step")'.
1427** larger than it was at the end of the last major collection (kept
1428** in 'g->GCestimate'), the function does a major collection. At the
1429** end, it checks whether the major collection was able to free a
1430** decent amount of memory (at least half the growth in memory since
1431** previous major collection). If so, the collector keeps its state,
1432** and the next collection will probably be minor again. Otherwise,
1433** we have what we call a "bad collection". In that case, set the field
1434** 'g->lastatomic' to signal that fact, so that the next collection will
1435** go to 'stepgenfull'.
1436**
1437** 'GCdebt <= 0' means an explicit call to GC step with "size" zero;
1438** in that case, do a minor collection.
1439*/ 1383*/
1440static void genstep (lua_State *L, global_State *g) { 1384static void genstep (lua_State *L, global_State *g) {
1441 if (g->lastatomic != 0) /* last collection was a bad one? */ 1385 l_obj majorbase = g->GClastmajor; /* count after last major collection */
1442 stepgenfull(L, g); /* do a full step */ 1386 l_obj majorinc = applygcparam(g, genmajormul, majorbase);
1443 else { 1387 if (g->GCdebt != 0 && gettotalobjs(g) > majorbase + majorinc) {
1444 lu_mem majorbase = g->GCestimate; /* memory after last major collection */ 1388 /* do a major collection */
1445 lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); 1389 enterinc(g);
1446 if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { 1390 g->gckind = KGC_GENMAJOR;
1447 lu_mem numobjs = fullgen(L, g); /* do a major collection */ 1391 genmajorstep(L, g);
1448 if (gettotalbytes(g) < majorbase + (majorinc / 2)) { 1392 }
1449 /* collected at least half of memory growth since last major 1393 else { /* regular case; do a minor collection */
1450 collection; keep doing minor collections. */ 1394 g->marked = 0;
1451 lua_assert(g->lastatomic == 0); 1395 youngcollection(L, g);
1452 } 1396 setminordebt(g);
1453 else { /* bad collection */ 1397 lua_assert(g->GClastmajor == majorbase);
1454 g->lastatomic = numobjs; /* signal that last collection was bad */
1455 setpause(g); /* do a long wait for next (major) collection */
1456 }
1457 }
1458 else { /* regular case; do a minor collection */
1459 youngcollection(L, g);
1460 setminordebt(g);
1461 g->GCestimate = majorbase; /* preserve base value */
1462 }
1463 } 1398 }
1464 lua_assert(isdecGCmodegen(g));
1465} 1399}
1466 1400
1467/* }====================================================== */ 1401/* }====================================================== */
@@ -1520,9 +1454,9 @@ void luaC_freeallobjects (lua_State *L) {
1520} 1454}
1521 1455
1522 1456
1523static lu_mem atomic (lua_State *L) { 1457static l_obj atomic (lua_State *L) {
1458 l_obj work = 0;
1524 global_State *g = G(L); 1459 global_State *g = G(L);
1525 lu_mem work = 0;
1526 GCObject *origweak, *origall; 1460 GCObject *origweak, *origall;
1527 GCObject *grayagain = g->grayagain; /* save original list */ 1461 GCObject *grayagain = g->grayagain; /* save original list */
1528 g->grayagain = NULL; 1462 g->grayagain = NULL;
@@ -1539,50 +1473,44 @@ static lu_mem atomic (lua_State *L) {
1539 work += propagateall(g); /* propagate changes */ 1473 work += propagateall(g); /* propagate changes */
1540 g->gray = grayagain; 1474 g->gray = grayagain;
1541 work += propagateall(g); /* traverse 'grayagain' list */ 1475 work += propagateall(g); /* traverse 'grayagain' list */
1542 convergeephemerons(g); 1476 work += convergeephemerons(g);
1543 /* at this point, all strongly accessible objects are marked. */ 1477 /* at this point, all strongly accessible objects are marked. */
1544 /* Clear values from weak tables, before checking finalizers */ 1478 /* Clear values from weak tables, before checking finalizers */
1545 clearbyvalues(g, g->weak, NULL); 1479 work += clearbyvalues(g, g->weak, NULL);
1546 clearbyvalues(g, g->allweak, NULL); 1480 work += clearbyvalues(g, g->allweak, NULL);
1547 origweak = g->weak; origall = g->allweak; 1481 origweak = g->weak; origall = g->allweak;
1548 separatetobefnz(g, 0); /* separate objects to be finalized */ 1482 separatetobefnz(g, 0); /* separate objects to be finalized */
1549 work += markbeingfnz(g); /* mark objects that will be finalized */ 1483 work += markbeingfnz(g); /* mark objects that will be finalized */
1550 work += propagateall(g); /* remark, to propagate 'resurrection' */ 1484 work += propagateall(g); /* remark, to propagate 'resurrection' */
1551 convergeephemerons(g); 1485 work += convergeephemerons(g);
1552 /* at this point, all resurrected objects are marked. */ 1486 /* at this point, all resurrected objects are marked. */
1553 /* remove dead objects from weak tables */ 1487 /* remove dead objects from weak tables */
1554 clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ 1488 work += clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */
1555 clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ 1489 work += clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */
1556 /* clear values from resurrected weak tables */ 1490 /* clear values from resurrected weak tables */
1557 clearbyvalues(g, g->weak, origweak); 1491 work += clearbyvalues(g, g->weak, origweak);
1558 clearbyvalues(g, g->allweak, origall); 1492 work += clearbyvalues(g, g->allweak, origall);
1559 luaS_clearcache(g); 1493 luaS_clearcache(g);
1560 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1494 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
1561 lua_assert(g->gray == NULL); 1495 lua_assert(g->gray == NULL);
1562 return work; /* estimate of slots marked by 'atomic' */ 1496 return work;
1563} 1497}
1564 1498
1565 1499
1566static int sweepstep (lua_State *L, global_State *g, 1500static void sweepstep (lua_State *L, global_State *g,
1567 int nextstate, GCObject **nextlist) { 1501 int nextstate, GCObject **nextlist) {
1568 if (g->sweepgc) { 1502 if (g->sweepgc)
1569 l_mem olddebt = g->GCdebt; 1503 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
1570 int count;
1571 g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count);
1572 g->GCestimate += g->GCdebt - olddebt; /* update estimate */
1573 return count;
1574 }
1575 else { /* enter next state */ 1504 else { /* enter next state */
1576 g->gcstate = nextstate; 1505 g->gcstate = nextstate;
1577 g->sweepgc = nextlist; 1506 g->sweepgc = nextlist;
1578 return 0; /* no work done */
1579 } 1507 }
1580} 1508}
1581 1509
1582 1510
1583static lu_mem singlestep (lua_State *L) { 1511static l_obj singlestep (lua_State *L) {
1584 global_State *g = G(L); 1512 global_State *g = G(L);
1585 lu_mem work; 1513 l_obj work;
1586 lua_assert(!g->gcstopem); /* collector is not reentrant */ 1514 lua_assert(!g->gcstopem); /* collector is not reentrant */
1587 g->gcstopem = 1; /* no emergency collections while collecting */ 1515 g->gcstopem = 1; /* no emergency collections while collecting */
1588 switch (g->gcstate) { 1516 switch (g->gcstate) {
@@ -1597,26 +1525,30 @@ static lu_mem singlestep (lua_State *L) {
1597 g->gcstate = GCSenteratomic; /* finish propagate phase */ 1525 g->gcstate = GCSenteratomic; /* finish propagate phase */
1598 work = 0; 1526 work = 0;
1599 } 1527 }
1600 else 1528 else {
1601 work = propagatemark(g); /* traverse one gray object */ 1529 propagatemark(g); /* traverse one gray object */
1530 work = 1;
1531 }
1602 break; 1532 break;
1603 } 1533 }
1604 case GCSenteratomic: { 1534 case GCSenteratomic: {
1605 work = atomic(L); /* work is what was traversed by 'atomic' */ 1535 work = atomic(L);
1606 entersweep(L); 1536 entersweep(L);
1607 g->GCestimate = gettotalbytes(g); /* first estimate */;
1608 break; 1537 break;
1609 } 1538 }
1610 case GCSswpallgc: { /* sweep "regular" objects */ 1539 case GCSswpallgc: { /* sweep "regular" objects */
1611 work = sweepstep(L, g, GCSswpfinobj, &g->finobj); 1540 sweepstep(L, g, GCSswpfinobj, &g->finobj);
1541 work = GCSWEEPMAX;
1612 break; 1542 break;
1613 } 1543 }
1614 case GCSswpfinobj: { /* sweep objects with finalizers */ 1544 case GCSswpfinobj: { /* sweep objects with finalizers */
1615 work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); 1545 sweepstep(L, g, GCSswptobefnz, &g->tobefnz);
1546 work = GCSWEEPMAX;
1616 break; 1547 break;
1617 } 1548 }
1618 case GCSswptobefnz: { /* sweep objects to be finalized */ 1549 case GCSswptobefnz: { /* sweep objects to be finalized */
1619 work = sweepstep(L, g, GCSswpend, NULL); 1550 sweepstep(L, g, GCSswpend, NULL);
1551 work = GCSWEEPMAX;
1620 break; 1552 break;
1621 } 1553 }
1622 case GCSswpend: { /* finish sweeps */ 1554 case GCSswpend: { /* finish sweeps */
@@ -1625,10 +1557,11 @@ static lu_mem singlestep (lua_State *L) {
1625 work = 0; 1557 work = 0;
1626 break; 1558 break;
1627 } 1559 }
1628 case GCScallfin: { /* call remaining finalizers */ 1560 case GCScallfin: { /* call finalizers */
1629 if (g->tobefnz && !g->gcemergency) { 1561 if (g->tobefnz && !g->gcemergency) {
1630 g->gcstopem = 0; /* ok collections during finalizers */ 1562 g->gcstopem = 0; /* ok collections during finalizers */
1631 work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; 1563 GCTM(L); /* call one finalizer */
1564 work = 1;
1632 } 1565 }
1633 else { /* emergency mode or no more finalizers */ 1566 else { /* emergency mode or no more finalizers */
1634 g->gcstate = GCSpause; /* finish collection */ 1567 g->gcstate = GCSpause; /* finish collection */
@@ -1663,20 +1596,16 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
1663** controls when next step will be performed. 1596** controls when next step will be performed.
1664*/ 1597*/
1665static void incstep (lua_State *L, global_State *g) { 1598static void incstep (lua_State *L, global_State *g) {
1666 int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ 1599 l_obj stepsize = cast(l_obj, 1) << g->gcstepsize;
1667 l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; 1600 l_obj work2do = applygcparam(g, gcstepmul, stepsize);
1668 l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem))
1669 ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul
1670 : MAX_LMEM; /* overflow; keep maximum value */
1671 do { /* repeat until pause or enough "credit" (negative debt) */ 1601 do { /* repeat until pause or enough "credit" (negative debt) */
1672 lu_mem work = singlestep(L); /* perform one single step */ 1602 l_obj work = singlestep(L); /* perform one single step */
1673 debt -= work; 1603 work2do -= work;
1674 } while (debt > -stepsize && g->gcstate != GCSpause); 1604 } while (work2do > 0 && g->gcstate != GCSpause);
1675 if (g->gcstate == GCSpause) 1605 if (g->gcstate == GCSpause)
1676 setpause(g); /* pause until next cycle */ 1606 setpause(g); /* pause until next cycle */
1677 else { 1607 else {
1678 debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ 1608 luaE_setdebt(g, stepsize);
1679 luaE_setdebt(g, debt);
1680 } 1609 }
1681} 1610}
1682 1611
@@ -1687,13 +1616,21 @@ static void incstep (lua_State *L, global_State *g) {
1687*/ 1616*/
1688void luaC_step (lua_State *L) { 1617void luaC_step (lua_State *L) {
1689 global_State *g = G(L); 1618 global_State *g = G(L);
1619 lua_assert(!g->gcemergency);
1690 if (!gcrunning(g)) /* not running? */ 1620 if (!gcrunning(g)) /* not running? */
1691 luaE_setdebt(g, -2000); 1621 luaE_setdebt(g, 2000);
1692 else { 1622 else {
1693 if(isdecGCmodegen(g)) 1623 switch (g->gckind) {
1694 genstep(L, g); 1624 case KGC_INC:
1695 else 1625 incstep(L, g);
1696 incstep(L, g); 1626 break;
1627 case KGC_GEN:
1628 genstep(L, g);
1629 break;
1630 case KGC_GENMAJOR:
1631 genmajorstep(L, g);
1632 break;
1633 }
1697 } 1634 }
1698} 1635}
1699 1636
@@ -1711,8 +1648,8 @@ static void fullinc (lua_State *L, global_State *g) {
1711 /* finish any pending sweep phase to start a new cycle */ 1648 /* finish any pending sweep phase to start a new cycle */
1712 luaC_runtilstate(L, bitmask(GCSpause)); 1649 luaC_runtilstate(L, bitmask(GCSpause));
1713 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ 1650 luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */
1714 /* estimate must be correct after a full GC cycle */ 1651 /* 'marked' must be correct after a full GC cycle */
1715 lua_assert(g->GCestimate == gettotalbytes(g)); 1652 lua_assert(g->marked == gettotalobjs(g));
1716 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ 1653 luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */
1717 setpause(g); 1654 setpause(g);
1718} 1655}
@@ -1727,10 +1664,10 @@ void luaC_fullgc (lua_State *L, int isemergency) {
1727 global_State *g = G(L); 1664 global_State *g = G(L);
1728 lua_assert(!g->gcemergency); 1665 lua_assert(!g->gcemergency);
1729 g->gcemergency = isemergency; /* set flag */ 1666 g->gcemergency = isemergency; /* set flag */
1730 if (g->gckind == KGC_INC) 1667 if (g->gckind == KGC_GEN)
1731 fullinc(L, g);
1732 else
1733 fullgen(L, g); 1668 fullgen(L, g);
1669 else
1670 fullinc(L, g);
1734 g->gcemergency = 0; 1671 g->gcemergency = 0;
1735} 1672}
1736 1673