diff options
| -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 | ||
