diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-11-18 11:13:47 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-11-18 11:13:47 -0200 |
| commit | ce444bff336b333251ac3745f311bd9033be8f6a (patch) | |
| tree | 92a3de426c0e4b66420dd3b6a911d45b3f5fd03d | |
| parent | 2d5931ebc8c3136bae92b5c502f3de0f06c31364 (diff) | |
| download | lua-ce444bff336b333251ac3745f311bd9033be8f6a.tar.gz lua-ce444bff336b333251ac3745f311bd9033be8f6a.tar.bz2 lua-ce444bff336b333251ac3745f311bd9033be8f6a.zip | |
(huge) simplification of GC management
| -rw-r--r-- | lgc.c | 133 | ||||
| -rw-r--r-- | lgc.h | 7 | ||||
| -rw-r--r-- | lstate.c | 14 | ||||
| -rw-r--r-- | lstate.h | 6 |
4 files changed, 50 insertions, 110 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.60 2009/11/06 17:06:19 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.61 2009/11/09 18:29:21 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 | */ |
| @@ -52,9 +52,6 @@ | |||
| 52 | reallymarkobject(g, obj2gco(t)); } | 52 | reallymarkobject(g, obj2gco(t)); } |
| 53 | 53 | ||
| 54 | 54 | ||
| 55 | #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) | ||
| 56 | |||
| 57 | |||
| 58 | static void reallymarkobject (global_State *g, GCObject *o); | 55 | static void reallymarkobject (global_State *g, GCObject *o); |
| 59 | 56 | ||
| 60 | 57 | ||
| @@ -94,6 +91,7 @@ static int iscleared (const TValue *o, int iskey) { | |||
| 94 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); | 91 | (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); |
| 95 | } | 92 | } |
| 96 | 93 | ||
| 94 | |||
| 97 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 95 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { |
| 98 | global_State *g = G(L); | 96 | global_State *g = G(L); |
| 99 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 97 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
| @@ -363,7 +361,6 @@ static void traverseproto (global_State *g, Proto *f) { | |||
| 363 | } | 361 | } |
| 364 | 362 | ||
| 365 | 363 | ||
| 366 | |||
| 367 | static void traverseclosure (global_State *g, Closure *cl) { | 364 | static void traverseclosure (global_State *g, Closure *cl) { |
| 368 | markobject(g, cl->c.env); | 365 | markobject(g, cl->c.env); |
| 369 | if (cl->c.isC) { | 366 | if (cl->c.isC) { |
| @@ -443,10 +440,8 @@ static l_mem propagatemark (global_State *g) { | |||
| 443 | } | 440 | } |
| 444 | 441 | ||
| 445 | 442 | ||
| 446 | static size_t propagateall (global_State *g) { | 443 | static void propagateall (global_State *g) { |
| 447 | size_t m = 0; | 444 | while (g->gray) propagatemark(g); |
| 448 | while (g->gray) m += propagatemark(g); | ||
| 449 | return m; | ||
| 450 | } | 445 | } |
| 451 | 446 | ||
| 452 | 447 | ||
| @@ -615,6 +610,8 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
| 615 | setuvalue(L, L->top+1, udata); | 610 | setuvalue(L, L->top+1, udata); |
| 616 | L->top += 2; | 611 | L->top += 2; |
| 617 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); | 612 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); |
| 613 | L->allowhook = oldah; /* restore hooks */ | ||
| 614 | g->GCthreshold = oldt; /* restore threshold */ | ||
| 618 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ | 615 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ |
| 619 | if (status == LUA_ERRRUN) { /* is there an error msg.? */ | 616 | if (status == LUA_ERRRUN) { /* is there an error msg.? */ |
| 620 | luaO_pushfstring(L, "error in __gc tag method (%s)", | 617 | luaO_pushfstring(L, "error in __gc tag method (%s)", |
| @@ -623,24 +620,13 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
| 623 | } | 620 | } |
| 624 | luaD_throw(L, status); /* re-send error */ | 621 | luaD_throw(L, status); /* re-send error */ |
| 625 | } | 622 | } |
| 626 | L->allowhook = oldah; /* restore hooks */ | ||
| 627 | g->GCthreshold = oldt; /* restore threshold */ | ||
| 628 | } | 623 | } |
| 629 | } | 624 | } |
| 630 | 625 | ||
| 631 | 626 | ||
| 632 | /* | ||
| 633 | ** Call all GC tag methods (without raising errors) | ||
| 634 | */ | ||
| 635 | void luaC_callAllGCTM (lua_State *L) { | ||
| 636 | while (G(L)->tobefnz) GCTM(L, 0); | ||
| 637 | } | ||
| 638 | |||
| 639 | |||
| 640 | /* move 'dead' udata that need finalization to list 'tobefnz' */ | 627 | /* move 'dead' udata that need finalization to list 'tobefnz' */ |
| 641 | size_t luaC_separateudata (lua_State *L, int all) { | 628 | void luaC_separateudata (lua_State *L, int all) { |
| 642 | global_State *g = G(L); | 629 | global_State *g = G(L); |
| 643 | size_t deadmem = 0; /* total size of all objects to be finalized */ | ||
| 644 | GCObject **p = &g->mainthread->next; | 630 | GCObject **p = &g->mainthread->next; |
| 645 | GCObject *curr; | 631 | GCObject *curr; |
| 646 | GCObject **lastnext = &g->tobefnz; | 632 | GCObject **lastnext = &g->tobefnz; |
| @@ -653,7 +639,6 @@ size_t luaC_separateudata (lua_State *L, int all) { | |||
| 653 | p = &gch(curr)->next; /* don't bother with it */ | 639 | p = &gch(curr)->next; /* don't bother with it */ |
| 654 | else { | 640 | else { |
| 655 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ | 641 | l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ |
| 656 | deadmem += sizeudata(gco2u(curr)); | ||
| 657 | *p = gch(curr)->next; /* remove 'curr' from 'rootgc' list */ | 642 | *p = gch(curr)->next; /* remove 'curr' from 'rootgc' list */ |
| 658 | /* link 'curr' at the end of 'tobefnz' list */ | 643 | /* link 'curr' at the end of 'tobefnz' list */ |
| 659 | gch(curr)->next = *lastnext; | 644 | gch(curr)->next = *lastnext; |
| @@ -661,7 +646,6 @@ size_t luaC_separateudata (lua_State *L, int all) { | |||
| 661 | lastnext = &gch(curr)->next; | 646 | lastnext = &gch(curr)->next; |
| 662 | } | 647 | } |
| 663 | } | 648 | } |
| 664 | return deadmem; | ||
| 665 | } | 649 | } |
| 666 | 650 | ||
| 667 | 651 | ||
| @@ -691,15 +675,15 @@ void luaC_checkfinalizer (lua_State *L, Udata *u) { | |||
| 691 | ** ======================================================= | 675 | ** ======================================================= |
| 692 | */ | 676 | */ |
| 693 | 677 | ||
| 694 | void luaC_freeall (lua_State *L) { | 678 | void luaC_freeallobjects (lua_State *L) { |
| 695 | global_State *g = G(L); | 679 | global_State *g = G(L); |
| 696 | int i; | 680 | int i; |
| 697 | lua_assert(g->tobefnz == NULL); | 681 | while (g->tobefnz) GCTM(L, 0); /* Call all pending finalizers */ |
| 698 | /* mask to collect all elements */ | 682 | /* following "white" makes all objects look dead */ |
| 699 | g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); | 683 | g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); |
| 700 | sweepwholelist(L, &g->rootgc); | 684 | sweepwholelist(L, &g->rootgc); |
| 701 | lua_assert(g->rootgc == obj2gco(g->mainthread)); | 685 | lua_assert(g->rootgc == obj2gco(g->mainthread) && |
| 702 | lua_assert(g->mainthread->next == NULL); | 686 | g->mainthread->next == NULL); |
| 703 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ | 687 | for (i = 0; i < g->strt.size; i++) /* free all string lists */ |
| 704 | sweepwholelist(L, &g->strt.hash[i]); | 688 | sweepwholelist(L, &g->strt.hash[i]); |
| 705 | lua_assert(g->strt.nuse == 0); | 689 | lua_assert(g->strt.nuse == 0); |
| @@ -708,49 +692,37 @@ void luaC_freeall (lua_State *L) { | |||
| 708 | 692 | ||
| 709 | static void atomic (lua_State *L) { | 693 | static void atomic (lua_State *L) { |
| 710 | global_State *g = G(L); | 694 | global_State *g = G(L); |
| 711 | size_t udsize; /* total size of userdata to be finalized */ | 695 | g->gcstate = GCSatomic; |
| 712 | /* global table and registry may be changed by API */ | 696 | lua_assert(!iswhite(obj2gco(g->mainthread))); |
| 697 | markobject(g, L); /* mark running thread */ | ||
| 698 | /* global table, registry, and global metatables may be changed by API */ | ||
| 713 | markvalue(g, &g->l_gt); | 699 | markvalue(g, &g->l_gt); |
| 714 | markvalue(g, &g->l_registry); | 700 | markvalue(g, &g->l_registry); |
| 701 | markmt(g); /* mark basic metatables */ | ||
| 715 | /* remark occasional upvalues of (maybe) dead threads */ | 702 | /* remark occasional upvalues of (maybe) dead threads */ |
| 716 | g->gcstate = GCSatomic; | ||
| 717 | remarkupvals(g); | 703 | remarkupvals(g); |
| 718 | /* traverse objects caught by write barrier and by 'remarkupvals' */ | 704 | /* traverse objects caught by write barrier and by 'remarkupvals' */ |
| 719 | propagateall(g); | 705 | propagateall(g); |
| 720 | /* remark weak tables */ | 706 | /* at this point, all strongly accessible objects are marked. |
| 721 | g->gray = g->weak; | 707 | Start marking weakily accessible objects. */ |
| 722 | g->weak = NULL; | 708 | traverselistofgrays(g, &g->weak); /* remark weak tables */ |
| 723 | lua_assert(!iswhite(obj2gco(g->mainthread))); | ||
| 724 | markobject(g, L); /* mark running thread */ | ||
| 725 | markmt(g); /* mark basic metatables (again) */ | ||
| 726 | propagateall(g); | ||
| 727 | traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */ | 709 | traverselistofgrays(g, &g->ephemeron); /* remark ephemeron tables */ |
| 728 | traverselistofgrays(g, &g->grayagain); /* remark gray again */ | 710 | traverselistofgrays(g, &g->grayagain); /* remark gray again */ |
| 729 | convergeephemerons(g); | 711 | convergeephemerons(g); |
| 730 | udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ | 712 | luaC_separateudata(L, 0); /* separate userdata to be finalized */ |
| 731 | markbeingfnz(g); /* mark userdata that will be finalized */ | 713 | markbeingfnz(g); /* mark userdata that will be finalized */ |
| 732 | udsize += propagateall(g); /* remark, to propagate `preserveness' */ | 714 | propagateall(g); /* remark, to propagate `preserveness' */ |
| 733 | convergeephemerons(g); | 715 | convergeephemerons(g); |
| 734 | /* remove collected objects from weak tables */ | 716 | /* remove collected objects from weak tables */ |
| 735 | cleartable(g->weak); | 717 | cleartable(g->weak); |
| 736 | cleartable(g->ephemeron); | 718 | cleartable(g->ephemeron); |
| 737 | cleartable(g->allweak); | 719 | cleartable(g->allweak); |
| 738 | /* flip current white */ | 720 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
| 739 | g->currentwhite = cast_byte(otherwhite(g)); | 721 | g->sweepstrgc = 0; /* go to sweep phase */ |
| 740 | g->sweepstrgc = 0; | ||
| 741 | g->gcstate = GCSsweepstring; | 722 | g->gcstate = GCSsweepstring; |
| 742 | lua_assert(g->totalbytes > udsize); | ||
| 743 | g->estimate = g->totalbytes - udsize; /* first estimate */ | ||
| 744 | } | 723 | } |
| 745 | 724 | ||
| 746 | 725 | ||
| 747 | #define correctestimate(g,s) { \ | ||
| 748 | lu_mem old = g->totalbytes; s; \ | ||
| 749 | lua_assert(old >= g->totalbytes); \ | ||
| 750 | if (g->estimate >= old - g->totalbytes) \ | ||
| 751 | g->estimate -= (old - g->totalbytes);} | ||
| 752 | |||
| 753 | |||
| 754 | static l_mem singlestep (lua_State *L) { | 726 | static l_mem singlestep (lua_State *L) { |
| 755 | global_State *g = G(L); | 727 | global_State *g = G(L); |
| 756 | /*lua_checkmemory(L);*/ | 728 | /*lua_checkmemory(L);*/ |
| @@ -768,7 +740,7 @@ static l_mem singlestep (lua_State *L) { | |||
| 768 | } | 740 | } |
| 769 | } | 741 | } |
| 770 | case GCSsweepstring: { | 742 | case GCSsweepstring: { |
| 771 | correctestimate(g, sweepwholelist(L, &g->strt.hash[g->sweepstrgc++])); | 743 | sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); |
| 772 | if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */ | 744 | if (g->sweepstrgc >= g->strt.size) { /* nothing more to sweep? */ |
| 773 | g->sweepgc = &g->rootgc; | 745 | g->sweepgc = &g->rootgc; |
| 774 | g->gcstate = GCSsweep; /* sweep all other objects */ | 746 | g->gcstate = GCSsweep; /* sweep all other objects */ |
| @@ -776,7 +748,7 @@ static l_mem singlestep (lua_State *L) { | |||
| 776 | return GCSWEEPCOST; | 748 | return GCSWEEPCOST; |
| 777 | } | 749 | } |
| 778 | case GCSsweep: { | 750 | case GCSsweep: { |
| 779 | correctestimate(g, g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX)); | 751 | g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); |
| 780 | if (*g->sweepgc == NULL) /* nothing more to sweep? */ | 752 | if (*g->sweepgc == NULL) /* nothing more to sweep? */ |
| 781 | g->gcstate = GCSfinalize; /* end sweep phase */ | 753 | g->gcstate = GCSfinalize; /* end sweep phase */ |
| 782 | return GCSWEEPMAX*GCSWEEPCOST; | 754 | return GCSWEEPMAX*GCSWEEPCOST; |
| @@ -784,14 +756,11 @@ static l_mem singlestep (lua_State *L) { | |||
| 784 | case GCSfinalize: { | 756 | case GCSfinalize: { |
| 785 | if (g->tobefnz) { | 757 | if (g->tobefnz) { |
| 786 | GCTM(L, 1); | 758 | GCTM(L, 1); |
| 787 | if (g->estimate > GCFINALIZECOST) | ||
| 788 | g->estimate -= GCFINALIZECOST; | ||
| 789 | return GCFINALIZECOST; | 759 | return GCFINALIZECOST; |
| 790 | } | 760 | } |
| 791 | else { | 761 | else { |
| 792 | correctestimate(g, checkSizes(L)); | 762 | checkSizes(L); |
| 793 | g->gcstate = GCSpause; /* end collection */ | 763 | g->gcstate = GCSpause; /* end collection */ |
| 794 | g->gcdept = 0; | ||
| 795 | return 0; | 764 | return 0; |
| 796 | } | 765 | } |
| 797 | } | 766 | } |
| @@ -802,29 +771,17 @@ static l_mem singlestep (lua_State *L) { | |||
| 802 | 771 | ||
| 803 | void luaC_step (lua_State *L) { | 772 | void luaC_step (lua_State *L) { |
| 804 | global_State *g = G(L); | 773 | global_State *g = G(L); |
| 805 | l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; | 774 | l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; /* how much to work */ |
| 775 | lu_mem debt = g->totalbytes - g->GCthreshold; | ||
| 806 | lua_assert(g->gckind == KGC_NORMAL); | 776 | lua_assert(g->gckind == KGC_NORMAL); |
| 807 | if (lim == 0) | 777 | do { /* always perform at least one single step */ |
| 808 | lim = (MAX_LUMEM-1)/2; /* no limit */ | ||
| 809 | g->gcdept += g->totalbytes - g->GCthreshold; | ||
| 810 | do { | ||
| 811 | lim -= singlestep(L); | 778 | lim -= singlestep(L); |
| 812 | if (g->gcstate == GCSpause) | 779 | } while (lim > 0 && g->gcstate != GCSpause); |
| 813 | break; | 780 | g->GCthreshold = (g->gcstate != GCSpause) |
| 814 | } while (lim > 0); | 781 | ? g->totalbytes + GCSTEPSIZE |
| 815 | if (g->gcstate != GCSpause) { | 782 | : (g->totalbytes/100) * g->gcpause; |
| 816 | if (g->gcdept < GCSTEPSIZE) | 783 | /* compensate if GC is "behind schedule" (has some debt to pay) */ |
| 817 | g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ | 784 | if (g->GCthreshold > debt) g->GCthreshold -= debt; |
| 818 | else { | ||
| 819 | g->gcdept -= GCSTEPSIZE; | ||
| 820 | g->GCthreshold = g->totalbytes; | ||
| 821 | } | ||
| 822 | } | ||
| 823 | else { | ||
| 824 | if (g->estimate > g->totalbytes) | ||
| 825 | g->estimate = g->totalbytes; | ||
| 826 | setthreshold(g); | ||
| 827 | } | ||
| 828 | } | 785 | } |
| 829 | 786 | ||
| 830 | 787 | ||
| @@ -832,21 +789,15 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
| 832 | global_State *g = G(L); | 789 | global_State *g = G(L); |
| 833 | lua_assert(g->gckind == KGC_NORMAL); | 790 | lua_assert(g->gckind == KGC_NORMAL); |
| 834 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_FORCED; | 791 | g->gckind = isemergency ? KGC_EMERGENCY : KGC_FORCED; |
| 835 | if (g->gcstate <= GCSpropagate) { | 792 | if (g->gcstate == GCSpropagate) { /* marking phase? */ |
| 836 | /* reset other collector lists */ | 793 | /* must sweep all objects to turn them back to white |
| 837 | g->gray = NULL; | 794 | (as white does not change, nothing will be collected) */ |
| 838 | g->grayagain = NULL; | ||
| 839 | g->weak = g->ephemeron = g->allweak = NULL; | ||
| 840 | g->sweepstrgc = 0; | 795 | g->sweepstrgc = 0; |
| 841 | g->gcstate = GCSsweepstring; | 796 | g->gcstate = GCSsweepstring; |
| 842 | } | 797 | } |
| 843 | lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); | ||
| 844 | /* finish any pending sweep phase */ | 798 | /* finish any pending sweep phase */ |
| 845 | while (g->gcstate != GCSfinalize) { | 799 | while (issweep(g)) singlestep(L); |
| 846 | lua_assert(issweep(g)); | 800 | markroot(L); /* start a new collection */ |
| 847 | singlestep(L); | ||
| 848 | } | ||
| 849 | markroot(L); | ||
| 850 | /* run collector up to finalizers */ | 801 | /* run collector up to finalizers */ |
| 851 | while (g->gcstate != GCSfinalize) | 802 | while (g->gcstate != GCSfinalize) |
| 852 | singlestep(L); | 803 | singlestep(L); |
| @@ -855,7 +806,7 @@ void luaC_fullgc (lua_State *L, int isemergency) { | |||
| 855 | while (g->gcstate != GCSpause) | 806 | while (g->gcstate != GCSpause) |
| 856 | singlestep(L); | 807 | singlestep(L); |
| 857 | } | 808 | } |
| 858 | setthreshold(g); | 809 | g->GCthreshold = (g->totalbytes/100) * g->gcpause; |
| 859 | } | 810 | } |
| 860 | 811 | ||
| 861 | /* }====================================================== */ | 812 | /* }====================================================== */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 2.21 2009/06/08 19:35:59 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.22 2009/11/17 11:56:03 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 | */ |
| @@ -95,9 +95,8 @@ | |||
| 95 | #define luaC_objbarriert(L,t,o) \ | 95 | #define luaC_objbarriert(L,t,o) \ |
| 96 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } | 96 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } |
| 97 | 97 | ||
| 98 | LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); | 98 | LUAI_FUNC void luaC_separateudata (lua_State *L, int all); |
| 99 | LUAI_FUNC void luaC_callAllGCTM (lua_State *L); | 99 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); |
| 100 | LUAI_FUNC void luaC_freeall (lua_State *L); | ||
| 101 | LUAI_FUNC void luaC_step (lua_State *L); | 100 | LUAI_FUNC void luaC_step (lua_State *L); |
| 102 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); | 101 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); |
| 103 | LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); | 102 | LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 2.62 2009/10/05 16:44:33 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.63 2009/10/23 19:12:19 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 | */ |
| @@ -139,7 +139,6 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
| 139 | luaT_init(L); | 139 | luaT_init(L); |
| 140 | luaX_init(L); | 140 | luaX_init(L); |
| 141 | luaS_fix(luaS_newliteral(L, MEMERRMSG)); | 141 | luaS_fix(luaS_newliteral(L, MEMERRMSG)); |
| 142 | g->estimate = g->totalbytes; | ||
| 143 | g->GCthreshold = 4*g->totalbytes; | 142 | g->GCthreshold = 4*g->totalbytes; |
| 144 | } | 143 | } |
| 145 | 144 | ||
| @@ -170,7 +169,7 @@ static void preinit_state (lua_State *L, global_State *g) { | |||
| 170 | static void close_state (lua_State *L) { | 169 | static void close_state (lua_State *L) { |
| 171 | global_State *g = G(L); | 170 | global_State *g = G(L); |
| 172 | luaF_close(L, L->stack); /* close all upvalues for this thread */ | 171 | luaF_close(L, L->stack); /* close all upvalues for this thread */ |
| 173 | luaC_freeall(L); /* collect all objects */ | 172 | luaC_freeallobjects(L); /* collect all objects */ |
| 174 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); | 173 | luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); |
| 175 | luaZ_freebuffer(L, &g->buff); | 174 | luaZ_freebuffer(L, &g->buff); |
| 176 | freestack(L); | 175 | freestack(L); |
| @@ -241,16 +240,10 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 241 | g->version = lua_version(NULL); | 240 | g->version = lua_version(NULL); |
| 242 | g->gcstate = GCSpause; | 241 | g->gcstate = GCSpause; |
| 243 | g->rootgc = obj2gco(L); | 242 | g->rootgc = obj2gco(L); |
| 244 | g->sweepstrgc = 0; | ||
| 245 | g->sweepgc = &g->rootgc; | ||
| 246 | g->gray = NULL; | ||
| 247 | g->grayagain = NULL; | ||
| 248 | g->weak = g->ephemeron = g->allweak = NULL; | ||
| 249 | g->tobefnz = NULL; | 243 | g->tobefnz = NULL; |
| 250 | g->estimate = g->totalbytes = sizeof(LG); | 244 | g->totalbytes = sizeof(LG); |
| 251 | g->gcpause = LUAI_GCPAUSE; | 245 | g->gcpause = LUAI_GCPAUSE; |
| 252 | g->gcstepmul = LUAI_GCMUL; | 246 | g->gcstepmul = LUAI_GCMUL; |
| 253 | g->gcdept = 0; | ||
| 254 | for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; | 247 | for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL; |
| 255 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { | 248 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { |
| 256 | /* memory allocation error: free partial state */ | 249 | /* memory allocation error: free partial state */ |
| @@ -269,7 +262,6 @@ LUA_API void lua_close (lua_State *L) { | |||
| 269 | luaF_close(L, L->stack); /* close all upvalues for this thread */ | 262 | luaF_close(L, L->stack); /* close all upvalues for this thread */ |
| 270 | luaC_separateudata(L, 1); /* separate all udata with GC metamethods */ | 263 | luaC_separateudata(L, 1); /* separate all udata with GC metamethods */ |
| 271 | lua_assert(L->next == NULL); | 264 | lua_assert(L->next == NULL); |
| 272 | luaC_callAllGCTM(L); /* call GC metamethods for all udata */ | ||
| 273 | luai_userstateclose(L); | 265 | luai_userstateclose(L); |
| 274 | close_state(L); | 266 | close_state(L); |
| 275 | } | 267 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 2.46 2009/07/15 17:26:14 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.47 2009/10/23 19:12:19 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 | */ |
| @@ -132,10 +132,8 @@ typedef struct global_State { | |||
| 132 | GCObject *allweak; /* list of all-weak tables */ | 132 | GCObject *allweak; /* list of all-weak tables */ |
| 133 | GCObject *tobefnz; /* list of userdata to be GC */ | 133 | GCObject *tobefnz; /* list of userdata to be GC */ |
| 134 | Mbuffer buff; /* temporary buffer for string concatentation */ | 134 | Mbuffer buff; /* temporary buffer for string concatentation */ |
| 135 | lu_mem GCthreshold; | 135 | lu_mem GCthreshold; /* when totalbytes > GCthreshold, run GC step */ |
| 136 | lu_mem totalbytes; /* number of bytes currently allocated */ | 136 | lu_mem totalbytes; /* number of bytes currently allocated */ |
| 137 | lu_mem estimate; /* an estimate of number of bytes actually in use */ | ||
| 138 | lu_mem gcdept; /* how much GC is `behind schedule' */ | ||
| 139 | int gcpause; /* size of pause between successive GCs */ | 137 | int gcpause; /* size of pause between successive GCs */ |
| 140 | int gcstepmul; /* GC `granularity' */ | 138 | int gcstepmul; /* GC `granularity' */ |
| 141 | lua_CFunction panic; /* to be called in unprotected errors */ | 139 | lua_CFunction panic; /* to be called in unprotected errors */ |
