summaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2012-05-31 17:26:14 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2012-05-31 17:26:14 -0300
commitab2c3d5cdea7812b48127778359849dbc180349a (patch)
tree14630e5a2b2cdb8ba7cc4653dd734cfd1a755c55 /lgc.c
parent01e5f358bd58de5c78138575cc09ff7745d4d96d (diff)
downloadlua-ab2c3d5cdea7812b48127778359849dbc180349a.tar.gz
lua-ab2c3d5cdea7812b48127778359849dbc180349a.tar.bz2
lua-ab2c3d5cdea7812b48127778359849dbc180349a.zip
small bug in error handling of finalizers (cannot call lua_tostring
inside the core) + small bug in luaC_checkfinalizer (when avoiding remove object being sweeped from sweep list) + small changes in GC pace control (for the atomic part)
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c72
1 files changed, 45 insertions, 27 deletions
diff --git a/lgc.c b/lgc.c
index 52084ab0..796f7b59 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 2.130 2012/05/29 17:52:17 roberto Exp roberto $ 2** $Id: lgc.c,v 2.131 2012/05/30 16:01:10 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*/
@@ -753,6 +753,18 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
753 return (*p == NULL) ? NULL : p; 753 return (*p == NULL) ? NULL : p;
754} 754}
755 755
756
757/*
758** sweep a list until a live object (or end of list)
759*/
760static GCObject **sweeptolive (lua_State *L, GCObject **p) {
761 GCObject ** old = p;
762 do {
763 p = sweeplist(L, p, 1);
764 } while (p == old);
765 return p;
766}
767
756/* }====================================================== */ 768/* }====================================================== */
757 769
758 770
@@ -812,12 +824,14 @@ static void GCTM (lua_State *L, int propagateerrors) {
812 L->allowhook = oldah; /* restore hooks */ 824 L->allowhook = oldah; /* restore hooks */
813 g->gcrunning = running; /* restore state */ 825 g->gcrunning = running; /* restore state */
814 if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ 826 if (status != LUA_OK && propagateerrors) { /* error while running __gc? */
815 if (status == LUA_ERRRUN) { /* is there an error msg.? */ 827 if (status == LUA_ERRRUN) { /* is there an error object? */
816 luaO_pushfstring(L, "error in __gc metamethod (%s)", 828 const char *msg = (ttisstring(L->top - 1))
817 lua_tostring(L, -1)); 829 ? svalue(L->top - 1)
830 : "no message";
831 luaO_pushfstring(L, "error in __gc metamethod (%s)", msg);
818 status = LUA_ERRGCMM; /* error in __gc metamethod */ 832 status = LUA_ERRGCMM; /* error in __gc metamethod */
819 } 833 }
820 luaD_throw(L, status); /* re-send error */ 834 luaD_throw(L, status); /* re-throw error */
821 } 835 }
822 } 836 }
823} 837}
@@ -864,11 +878,9 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
864 else { /* move 'o' to 'finobj' list */ 878 else { /* move 'o' to 'finobj' list */
865 GCObject **p; 879 GCObject **p;
866 GCheader *ho = gch(o); 880 GCheader *ho = gch(o);
867 lua_assert(!isdead(g, o)); 881 if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */
868 /* avoid removing current sweep object */ 882 lua_assert(issweepphase(g));
869 if (g->sweepgc == &ho->next) { 883 g->sweepgc = sweeptolive(L, g->sweepgc);
870 /* step to next object in the list */
871 g->sweepgc = sweeplist(L, g->sweepgc, 1);
872 } 884 }
873 /* search for pointer pointing to 'o' */ 885 /* search for pointer pointing to 'o' */
874 for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } 886 for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
@@ -899,18 +911,19 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
899 911
900/* 912/*
901** enter first sweep phase (strings) and prepare pointers for other 913** enter first sweep phase (strings) and prepare pointers for other
902** sweep phases. The calls to 'sweeplist' attempt to make pointers 914** sweep phases. The calls to 'sweeptolive' make pointers point to an
903** point to an object inside the list (instead of to the header), so 915** object inside the list (instead of to the header), so that the real
904** that the real sweep do not need to skip objects created between "now" 916** sweep do not need to skip objects created between "now" and the start
905** and the start of the real sweep. 917** of the real sweep.
906*/ 918*/
907static void entersweep (lua_State *L) { 919static void entersweep (lua_State *L) {
908 global_State *g = G(L); 920 global_State *g = G(L);
909 g->gcstate = GCSsweepstring; 921 g->gcstate = GCSsweepstring;
910 lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); 922 lua_assert(g->sweepgc == NULL && g->sweepfin == NULL);
911 g->sweepstrgc = 0; /* prepare to sweep strings, ... */ 923 /* prepare to sweep strings, finalizable objects, and regular objects */
912 g->sweepfin = sweeplist(L, &g->finobj, 1); /* finalizable objects, ... */ 924 g->sweepstrgc = 0;
913 g->sweepgc = sweeplist(L, &g->allgc, 1); /* and regular objects */ 925 g->sweepfin = sweeptolive(L, &g->finobj);
926 g->sweepgc = sweeptolive(L, &g->allgc);
914} 927}
915 928
916 929
@@ -966,7 +979,7 @@ void luaC_freeallobjects (lua_State *L) {
966 979
967static l_mem atomic (lua_State *L) { 980static l_mem atomic (lua_State *L) {
968 global_State *g = G(L); 981 global_State *g = G(L);
969 l_mem trav = -g->GCmemtrav; /* start counting work */ 982 l_mem work = -g->GCmemtrav; /* start counting work */
970 GCObject *origweak, *origall; 983 GCObject *origweak, *origall;
971 lua_assert(!iswhite(obj2gco(g->mainthread))); 984 lua_assert(!iswhite(obj2gco(g->mainthread)));
972 markobject(g, L); /* mark running thread */ 985 markobject(g, L); /* mark running thread */
@@ -976,20 +989,21 @@ static l_mem atomic (lua_State *L) {
976 /* remark occasional upvalues of (maybe) dead threads */ 989 /* remark occasional upvalues of (maybe) dead threads */
977 remarkupvals(g); 990 remarkupvals(g);
978 propagateall(g); /* propagate changes */ 991 propagateall(g); /* propagate changes */
979 trav += g->GCmemtrav; /* count work done til now */ 992 work += g->GCmemtrav; /* stop counting (do not (re)count grays) */
980 /* traverse objects caught by write barrier and by 'remarkupvals' */ 993 /* traverse objects caught by write barrier and by 'remarkupvals' */
981 retraversegrays(g); 994 retraversegrays(g);
995 work -= g->GCmemtrav; /* restart counting */
982 convergeephemerons(g); 996 convergeephemerons(g);
983 /* at this point, all strongly accessible objects are marked. */ 997 /* at this point, all strongly accessible objects are marked. */
984 /* clear values from weak tables, before checking finalizers */ 998 /* clear values from weak tables, before checking finalizers */
985 clearvalues(g, g->weak, NULL); 999 clearvalues(g, g->weak, NULL);
986 clearvalues(g, g->allweak, NULL); 1000 clearvalues(g, g->allweak, NULL);
987 origweak = g->weak; origall = g->allweak; 1001 origweak = g->weak; origall = g->allweak;
988 trav -= g->GCmemtrav; /* restart counting work */ 1002 work += g->GCmemtrav; /* stop counting (objects being finalized) */
989 separatetobefnz(L, 0); /* separate objects to be finalized */ 1003 separatetobefnz(L, 0); /* separate objects to be finalized */
990 markbeingfnz(g); /* mark objects that will be finalized */ 1004 markbeingfnz(g); /* mark objects that will be finalized */
991 propagateall(g); /* remark, to propagate `preserveness' */ 1005 propagateall(g); /* remark, to propagate `preserveness' */
992 trav += g->GCmemtrav; /* add work done til now */ 1006 work -= g->GCmemtrav; /* restart counting */
993 convergeephemerons(g); 1007 convergeephemerons(g);
994 /* at this point, all resurrected objects are marked. */ 1008 /* at this point, all resurrected objects are marked. */
995 /* remove dead objects from weak tables */ 1009 /* remove dead objects from weak tables */
@@ -999,8 +1013,8 @@ static l_mem atomic (lua_State *L) {
999 clearvalues(g, g->weak, origweak); 1013 clearvalues(g, g->weak, origweak);
1000 clearvalues(g, g->allweak, origall); 1014 clearvalues(g, g->allweak, origall);
1001 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ 1015 g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
1002 entersweep(L); /* prepare to sweep strings */ 1016 work += g->GCmemtrav; /* complete counting */
1003 return trav; /* estimate of the objects marked by 'atomic' */ 1017 return work; /* estimate of memory marked by 'atomic' */
1004} 1018}
1005 1019
1006 1020
@@ -1024,9 +1038,13 @@ static lu_mem singlestep (lua_State *L) {
1024 return g->GCmemtrav - oldtrav; /* memory traversed in this step */ 1038 return g->GCmemtrav - oldtrav; /* memory traversed in this step */
1025 } 1039 }
1026 else { /* no more `gray' objects */ 1040 else { /* no more `gray' objects */
1041 lu_mem work;
1027 g->gcstate = GCSatomic; /* finish mark phase */ 1042 g->gcstate = GCSatomic; /* finish mark phase */
1028 g->GCestimate = g->GCmemtrav; /* save what was counted */ 1043 g->GCestimate = g->GCmemtrav; /* save what was counted */;
1029 return atomic(L); 1044 work = atomic(L); /* add what was traversed by 'atomic' */
1045 g->GCestimate += work; /* estimate of total memory traversed */
1046 entersweep(L);
1047 return work + 2 * GCSWEEPCOST;
1030 } 1048 }
1031 } 1049 }
1032 case GCSsweepstring: { 1050 case GCSsweepstring: {
@@ -1095,7 +1113,7 @@ static void generationalcollection (lua_State *L) {
1095} 1113}
1096 1114
1097 1115
1098static void step (lua_State *L) { 1116static void incstep (lua_State *L) {
1099 global_State *g = G(L); 1117 global_State *g = G(L);
1100 l_mem debt = g->GCdebt; 1118 l_mem debt = g->GCdebt;
1101 int stepmul = g->gcstepmul; 1119 int stepmul = g->gcstepmul;
@@ -1122,7 +1140,7 @@ void luaC_forcestep (lua_State *L) {
1122 global_State *g = G(L); 1140 global_State *g = G(L);
1123 int i; 1141 int i;
1124 if (isgenerational(g)) generationalcollection(L); 1142 if (isgenerational(g)) generationalcollection(L);
1125 else step(L); 1143 else incstep(L);
1126 /* run a few finalizers (or all of them at the end of a collect cycle) */ 1144 /* run a few finalizers (or all of them at the end of a collect cycle) */
1127 for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) 1145 for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++)
1128 GCTM(L, 1); /* call one finalizer */ 1146 GCTM(L, 1); /* call one finalizer */