diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-26 09:41:10 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-26 09:41:10 -0300 |
commit | 742b7377d38e43224ee5dda4bb83a42763c20af8 (patch) | |
tree | 7caeaa7077ff6414f20646b7cef5308ad5bc2199 /lgc.c | |
parent | 50955e27f592441a223c6267956e470f98eeb3c0 (diff) | |
download | lua-742b7377d38e43224ee5dda4bb83a42763c20af8.tar.gz lua-742b7377d38e43224ee5dda4bb83a42763c20af8.tar.bz2 lua-742b7377d38e43224ee5dda4bb83a42763c20af8.zip |
Lua closures go to local, too
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 41 |
1 files changed, 35 insertions, 6 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.150 2013/08/21 20:09:51 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.151 2013/08/23 13:34:54 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 | */ |
@@ -885,6 +885,17 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { | |||
885 | ** ======================================================= | 885 | ** ======================================================= |
886 | */ | 886 | */ |
887 | 887 | ||
888 | |||
889 | static void localmarkclosure (LClosure *cl, int bit) { | ||
890 | int i; | ||
891 | for (i = 0; i < cl->nupvalues; i++) { | ||
892 | if (cl->upvals[i]) { | ||
893 | l_setbit(cl->upvals[i]->marked, bit); | ||
894 | } | ||
895 | } | ||
896 | } | ||
897 | |||
898 | |||
888 | /* | 899 | /* |
889 | ** Traverse a thread, local marking all its collectable objects | 900 | ** Traverse a thread, local marking all its collectable objects |
890 | */ | 901 | */ |
@@ -893,8 +904,16 @@ static void localmarkthread (lua_State *l) { | |||
893 | if (o == NULL) | 904 | if (o == NULL) |
894 | return; /* stack not completely built yet */ | 905 | return; /* stack not completely built yet */ |
895 | for (; o < l->top; o++) { /* mark live elements in the stack */ | 906 | for (; o < l->top; o++) { /* mark live elements in the stack */ |
896 | if (iscollectable(o)) | 907 | if (iscollectable(o)) { |
897 | l_setbit(gcvalue(o)->gch.marked, LOCALBLACK); | 908 | GCObject *obj = gcvalue(o); |
909 | if (obj->gch.tt == LUA_TLCL && /* is it a Lua closure? */ | ||
910 | islocal(obj) && /* is it still local? */ | ||
911 | !testbit(obj->gch.marked, LOCALBLACK)) { /* not visited yet? */ | ||
912 | /* mark its upvalues as local black */ | ||
913 | localmarkclosure(gco2lcl(obj), LOCALBLACK); | ||
914 | } | ||
915 | l_setbit(obj->gch.marked, LOCALBLACK); | ||
916 | } | ||
898 | } | 917 | } |
899 | } | 918 | } |
900 | 919 | ||
@@ -911,14 +930,17 @@ static void localmark (global_State *g) { | |||
911 | } | 930 | } |
912 | 931 | ||
913 | 932 | ||
914 | static void localsweep (lua_State *L, global_State *g) { | 933 | static void localsweep (lua_State *L, global_State *g, GCObject **p) { |
915 | GCObject **p = &g->localgc; | ||
916 | while (*p != NULL) { | 934 | while (*p != NULL) { |
917 | GCObject *curr = *p; | 935 | GCObject *curr = *p; |
918 | if (!islocal(curr)) { /* is 'curr' no more local? */ | 936 | if (!islocal(curr)) { /* is 'curr' no more local? */ |
919 | *p = curr->gch.next; /* remove 'curr' from list */ | 937 | *p = curr->gch.next; /* remove 'curr' from list */ |
920 | curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ | 938 | curr->gch.next = g->allgc; /* link 'curr' in 'allgc' list */ |
921 | g->allgc = curr; | 939 | g->allgc = curr; |
940 | if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */ | ||
941 | /* mark its upvalues as non local */ | ||
942 | localmarkclosure(gco2lcl(curr), LOCALBIT); | ||
943 | } | ||
922 | } | 944 | } |
923 | else { /* still local */ | 945 | else { /* still local */ |
924 | if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */ | 946 | if (testbit(curr->gch.marked, LOCALBLACK)) { /* locally alive? */ |
@@ -926,6 +948,10 @@ static void localsweep (lua_State *L, global_State *g) { | |||
926 | p = &curr->gch.next; /* go to next element */ | 948 | p = &curr->gch.next; /* go to next element */ |
927 | } | 949 | } |
928 | else { /* object is dead */ | 950 | else { /* object is dead */ |
951 | if (curr->gch.tt == LUA_TLCL) { /* is it a Lua closure? */ | ||
952 | if (gco2lcl(curr)->p->cache == gco2cl(curr)) | ||
953 | gco2lcl(curr)->p->cache = NULL; /* clear cache */ | ||
954 | } | ||
929 | *p = curr->gch.next; /* remove 'curr' from list */ | 955 | *p = curr->gch.next; /* remove 'curr' from list */ |
930 | freeobj(L, curr); /* erase 'curr' */ | 956 | freeobj(L, curr); /* erase 'curr' */ |
931 | } | 957 | } |
@@ -938,7 +964,8 @@ static void luaC_localcollection (lua_State *L) { | |||
938 | global_State *g = G(L); | 964 | global_State *g = G(L); |
939 | lua_assert(g->gcstate == GCSpause); | 965 | lua_assert(g->gcstate == GCSpause); |
940 | localmark(g); | 966 | localmark(g); |
941 | localsweep(L, g); | 967 | localsweep(L, g, &g->localgc); |
968 | localsweep(L, g, &g->localupv); | ||
942 | } | 969 | } |
943 | 970 | ||
944 | /* }====================================================== */ | 971 | /* }====================================================== */ |
@@ -1009,6 +1036,7 @@ void luaC_freeallobjects (lua_State *L) { | |||
1009 | g->gckind = KGC_NORMAL; | 1036 | g->gckind = KGC_NORMAL; |
1010 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ | 1037 | sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ |
1011 | sweepwholelist(L, &g->localgc); | 1038 | sweepwholelist(L, &g->localgc); |
1039 | sweepwholelist(L, &g->localupv); | ||
1012 | sweepwholelist(L, &g->allgc); | 1040 | sweepwholelist(L, &g->allgc); |
1013 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ | 1041 | sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ |
1014 | lua_assert(g->strt.nuse == 0); | 1042 | lua_assert(g->strt.nuse == 0); |
@@ -1091,6 +1119,7 @@ static lu_mem singlestep (lua_State *L) { | |||
1091 | } | 1119 | } |
1092 | else { | 1120 | else { |
1093 | sweepwholelist(L, &g->localgc); | 1121 | sweepwholelist(L, &g->localgc); |
1122 | sweepwholelist(L, &g->localupv); | ||
1094 | g->gcstate = GCSsweep; | 1123 | g->gcstate = GCSsweep; |
1095 | return GCLOCALPAUSE / 4; /* some magic for now */ | 1124 | return GCLOCALPAUSE / 4; /* some magic for now */ |
1096 | } | 1125 | } |