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 | |
parent | 50955e27f592441a223c6267956e470f98eeb3c0 (diff) | |
download | lua-742b7377d38e43224ee5dda4bb83a42763c20af8.tar.gz lua-742b7377d38e43224ee5dda4bb83a42763c20af8.tar.bz2 lua-742b7377d38e43224ee5dda4bb83a42763c20af8.zip |
Lua closures go to local, too
-rw-r--r-- | lfunc.c | 19 | ||||
-rw-r--r-- | lgc.c | 41 | ||||
-rw-r--r-- | lstate.c | 4 | ||||
-rw-r--r-- | lstate.h | 3 | ||||
-rw-r--r-- | ltests.c | 26 |
5 files changed, 72 insertions, 21 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lfunc.c,v 2.33 2013/08/16 18:55:49 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.34 2013/08/23 13:34:54 roberto Exp roberto $ |
3 | ** Auxiliary functions to manipulate prototypes and closures | 3 | ** Auxiliary functions to manipulate prototypes and closures |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -29,7 +29,8 @@ Closure *luaF_newCclosure (lua_State *L, int n) { | |||
29 | 29 | ||
30 | 30 | ||
31 | Closure *luaF_newLclosure (lua_State *L, int n) { | 31 | Closure *luaF_newLclosure (lua_State *L, int n) { |
32 | Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; | 32 | Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), |
33 | &G(L)->localgc, 0)->cl; | ||
33 | c->l.p = NULL; | 34 | c->l.p = NULL; |
34 | c->l.nupvalues = cast_byte(n); | 35 | c->l.nupvalues = cast_byte(n); |
35 | while (n--) c->l.upvals[n] = NULL; | 36 | while (n--) c->l.upvals[n] = NULL; |
@@ -38,7 +39,8 @@ Closure *luaF_newLclosure (lua_State *L, int n) { | |||
38 | 39 | ||
39 | 40 | ||
40 | UpVal *luaF_newupval (lua_State *L) { | 41 | UpVal *luaF_newupval (lua_State *L) { |
41 | UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; | 42 | UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), |
43 | &G(L)->localupv, 0)->uv; | ||
42 | uv->v = &uv->value; | 44 | uv->v = &uv->value; |
43 | setnilvalue(uv->v); | 45 | setnilvalue(uv->v); |
44 | return uv; | 46 | return uv; |
@@ -79,8 +81,15 @@ void luaF_close (lua_State *L, StkId level) { | |||
79 | else { | 81 | else { |
80 | setobj(L, &uv->value, uv->v); /* move value to upvalue slot */ | 82 | setobj(L, &uv->value, uv->v); /* move value to upvalue slot */ |
81 | uv->v = &uv->value; /* now current value lives here */ | 83 | uv->v = &uv->value; /* now current value lives here */ |
82 | gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ | 84 | if (islocal(o)) { |
83 | g->allgc = o; | 85 | gch(o)->next = g->localupv; /* link upvalue into 'localupv' list */ |
86 | g->localupv = o; | ||
87 | resetbit(o->gch.marked, LOCALBLACK); | ||
88 | } | ||
89 | else { /* link upvalue into 'allgc' list */ | ||
90 | gch(o)->next = g->allgc; | ||
91 | g->allgc = o; | ||
92 | } | ||
84 | valnolocal(uv->v); /* keep local invariant */ | 93 | valnolocal(uv->v); /* keep local invariant */ |
85 | luaC_checkupvalcolor(g, uv); | 94 | luaC_checkupvalcolor(g, uv); |
86 | } | 95 | } |
@@ -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 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.104 2013/08/21 20:09:51 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.105 2013/08/23 13:34:54 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 | */ |
@@ -289,7 +289,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
289 | g->version = lua_version(NULL); | 289 | g->version = lua_version(NULL); |
290 | g->gcstate = GCSpause; | 290 | g->gcstate = GCSpause; |
291 | g->allgc = NULL; | 291 | g->allgc = NULL; |
292 | g->localgc = NULL; | 292 | g->localgc = g->localupv = NULL; |
293 | g->finobj = NULL; | 293 | g->finobj = NULL; |
294 | g->tobefnz = NULL; | 294 | g->tobefnz = NULL; |
295 | g->fixedgc = NULL; | 295 | g->fixedgc = NULL; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.88 2013/08/22 15:21:48 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.89 2013/08/23 13:34:54 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 | */ |
@@ -128,6 +128,7 @@ typedef struct global_State { | |||
128 | lu_byte gcrunning; /* true if GC is running */ | 128 | lu_byte gcrunning; /* true if GC is running */ |
129 | GCObject *allgc; /* list of all collectable objects */ | 129 | GCObject *allgc; /* list of all collectable objects */ |
130 | GCObject *localgc; /* list of local objects */ | 130 | GCObject *localgc; /* list of local objects */ |
131 | GCObject *localupv; /* list of local upvalues */ | ||
131 | GCObject *finobj; /* list of collectable objects with finalizers */ | 132 | GCObject *finobj; /* list of collectable objects with finalizers */ |
132 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ | 133 | GCObject **sweepgc; /* current position of sweep in list 'allgc' */ |
133 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ | 134 | GCObject **sweepfin; /* current position of sweep in list 'finobj' */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.147 2013/08/21 19:21:16 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.148 2013/08/22 15:21:48 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -400,7 +400,8 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
400 | 400 | ||
401 | #define TESTGRAYBIT 7 | 401 | #define TESTGRAYBIT 7 |
402 | 402 | ||
403 | static void checkgraylist (GCObject *l) { | 403 | static void checkgraylist (global_State *g, GCObject *l) { |
404 | UNUSED(g); /* better to keep it available if we need to print an object */ | ||
404 | while (l) { | 405 | while (l) { |
405 | lua_assert(isgray(l)); | 406 | lua_assert(isgray(l)); |
406 | lua_assert(!testbit(l->gch.marked, TESTGRAYBIT)); | 407 | lua_assert(!testbit(l->gch.marked, TESTGRAYBIT)); |
@@ -423,11 +424,11 @@ static void checkgraylist (GCObject *l) { | |||
423 | */ | 424 | */ |
424 | static void markgrays (global_State *g) { | 425 | static void markgrays (global_State *g) { |
425 | if (!keepinvariant(g)) return; | 426 | if (!keepinvariant(g)) return; |
426 | checkgraylist(g->gray); | 427 | checkgraylist(g, g->gray); |
427 | checkgraylist(g->grayagain); | 428 | checkgraylist(g, g->grayagain); |
428 | checkgraylist(g->weak); | 429 | checkgraylist(g, g->weak); |
429 | checkgraylist(g->ephemeron); | 430 | checkgraylist(g, g->ephemeron); |
430 | checkgraylist(g->allweak); | 431 | checkgraylist(g, g->allweak); |
431 | } | 432 | } |
432 | 433 | ||
433 | 434 | ||
@@ -484,6 +485,17 @@ int lua_checkmemory (lua_State *L) { | |||
484 | lua_assert(gch(o)->tt == LUA_TUSERDATA || | 485 | lua_assert(gch(o)->tt == LUA_TUSERDATA || |
485 | gch(o)->tt == LUA_TTABLE); | 486 | gch(o)->tt == LUA_TTABLE); |
486 | } | 487 | } |
488 | /* check 'localgc' list */ | ||
489 | checkgray(g, g->localgc); | ||
490 | for (o = g->localgc; o != NULL; o = gch(o)->next) { | ||
491 | checkobject(g, o, 1); | ||
492 | } | ||
493 | /* check 'localupv' list */ | ||
494 | checkgray(g, g->localupv); | ||
495 | for (o = g->localupv; o != NULL; o = gch(o)->next) { | ||
496 | lua_assert(gch(o)->tt == LUA_TUPVAL); | ||
497 | checkobject(g, o, 1); | ||
498 | } | ||
487 | return 0; | 499 | return 0; |
488 | } | 500 | } |
489 | 501 | ||