diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-16 15:55:49 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-08-16 15:55:49 -0300 |
| commit | 439d74e29f3234a034777f88b260523afe8c0446 (patch) | |
| tree | a3ee160dccfd3cf0f065edbba07290c4ba9af93d | |
| parent | 3679d33b02782ff7d7d0fa163b815902b189c89e (diff) | |
| download | lua-439d74e29f3234a034777f88b260523afe8c0446.tar.gz lua-439d74e29f3234a034777f88b260523afe8c0446.tar.bz2 lua-439d74e29f3234a034777f88b260523afe8c0446.zip | |
added 'local' bit (true => object is only refered by local variables)
| -rw-r--r-- | lapi.c | 8 | ||||
| -rw-r--r-- | lfunc.c | 4 | ||||
| -rw-r--r-- | lgc.c | 26 | ||||
| -rw-r--r-- | lgc.h | 20 | ||||
| -rw-r--r-- | lparser.c | 3 | ||||
| -rw-r--r-- | lstate.c | 17 | ||||
| -rw-r--r-- | lstring.h | 4 | ||||
| -rw-r--r-- | ltests.c | 57 | ||||
| -rw-r--r-- | lundump.c | 7 | ||||
| -rw-r--r-- | lvm.c | 3 |
10 files changed, 96 insertions, 53 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.186 2013/08/05 16:58:28 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -586,8 +586,11 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { | |||
| 586 | cl = luaF_newCclosure(L, n); | 586 | cl = luaF_newCclosure(L, n); |
| 587 | cl->c.f = fn; | 587 | cl->c.f = fn; |
| 588 | L->top -= n; | 588 | L->top -= n; |
| 589 | while (n--) | 589 | while (n--) { |
| 590 | setobj2n(L, &cl->c.upvalue[n], L->top + n); | 590 | setobj2n(L, &cl->c.upvalue[n], L->top + n); |
| 591 | /* does not need barrier because closure is white */ | ||
| 592 | valnolocal(L->top + n); /* but needs 'local barrier' */ | ||
| 593 | } | ||
| 591 | setclCvalue(L, L->top, cl); | 594 | setclCvalue(L, L->top, cl); |
| 592 | } | 595 | } |
| 593 | api_incr_top(L); | 596 | api_incr_top(L); |
| @@ -861,6 +864,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
| 861 | } | 864 | } |
| 862 | default: { | 865 | default: { |
| 863 | G(L)->mt[ttnov(obj)] = mt; | 866 | G(L)->mt[ttnov(obj)] = mt; |
| 867 | if (mt) nolocal(obj2gco(mt)); | ||
| 864 | break; | 868 | break; |
| 865 | } | 869 | } |
| 866 | } | 870 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.c,v 2.31 2013/08/05 16:58:28 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.32 2013/08/07 12:18:11 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 | */ |
| @@ -80,6 +80,7 @@ void luaF_close (lua_State *L, StkId level) { | |||
| 80 | uv->v = &uv->value; /* now current value lives here */ | 80 | uv->v = &uv->value; /* now current value lives here */ |
| 81 | gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ | 81 | gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ |
| 82 | g->allgc = o; | 82 | g->allgc = o; |
| 83 | valnolocal(uv->v); /* keep local invariant */ | ||
| 83 | luaC_checkupvalcolor(g, uv); | 84 | luaC_checkupvalcolor(g, uv); |
| 84 | } | 85 | } |
| 85 | } | 86 | } |
| @@ -88,6 +89,7 @@ void luaF_close (lua_State *L, StkId level) { | |||
| 88 | 89 | ||
| 89 | Proto *luaF_newproto (lua_State *L) { | 90 | Proto *luaF_newproto (lua_State *L) { |
| 90 | Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; | 91 | Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; |
| 92 | nolocal(obj2gco(f)); /* prototypes are never local */ | ||
| 91 | f->k = NULL; | 93 | f->k = NULL; |
| 92 | f->sizek = 0; | 94 | f->sizek = 0; |
| 93 | f->p = NULL; | 95 | f->p = NULL; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.144 2013/08/07 15:39:09 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.145 2013/08/13 17:36:44 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 | */ |
| @@ -74,11 +74,19 @@ | |||
| 74 | lua_longassert(!iscollectable(obj) || righttt(obj)) | 74 | lua_longassert(!iscollectable(obj) || righttt(obj)) |
| 75 | 75 | ||
| 76 | 76 | ||
| 77 | #define markvalue(g,o) { checkconsistency(o); \ | 77 | #define marklocalvalue(g,o) { checkconsistency(o); \ |
| 78 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } | 78 | if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } |
| 79 | 79 | ||
| 80 | #define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ | 80 | #define markvalue(g,o) { \ |
| 81 | reallymarkobject(g, obj2gco(t)); } | 81 | lua_longassert(!(iscollectable(o) && islocal(gcvalue(o)))); \ |
| 82 | marklocalvalue(g,o); } | ||
| 83 | |||
| 84 | #define marklocalobject(g,t) { \ | ||
| 85 | if ((t) && iswhite(obj2gco(t))) \ | ||
| 86 | reallymarkobject(g, obj2gco(t)); } | ||
| 87 | |||
| 88 | #define markobject(g,t) \ | ||
| 89 | { lua_assert((t) == NULL || !islocal(obj2gco(t))); marklocalobject(g,t); } | ||
| 82 | 90 | ||
| 83 | static void reallymarkobject (global_State *g, GCObject *o); | 91 | static void reallymarkobject (global_State *g, GCObject *o); |
| 84 | 92 | ||
| @@ -259,7 +267,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 259 | } | 267 | } |
| 260 | case LUA_TUPVAL: { | 268 | case LUA_TUPVAL: { |
| 261 | UpVal *uv = gco2uv(o); | 269 | UpVal *uv = gco2uv(o); |
| 262 | markvalue(g, uv->v); | 270 | marklocalvalue(g, uv->v); |
| 263 | if (uv->v != &uv->value) /* open? */ | 271 | if (uv->v != &uv->value) /* open? */ |
| 264 | return; /* open upvalues remain gray */ | 272 | return; /* open upvalues remain gray */ |
| 265 | size = sizeof(UpVal); | 273 | size = sizeof(UpVal); |
| @@ -331,7 +339,7 @@ static void remarkupvals (global_State *g) { | |||
| 331 | GCObject *uv = gco2th(thread)->openupval; | 339 | GCObject *uv = gco2th(thread)->openupval; |
| 332 | for (; uv != NULL; uv = gch(uv)->next) { | 340 | for (; uv != NULL; uv = gch(uv)->next) { |
| 333 | if (isgray(uv)) /* marked? */ | 341 | if (isgray(uv)) /* marked? */ |
| 334 | markvalue(g, gco2uv(uv)->v); /* remark upvalue's value */ | 342 | marklocalvalue(g, gco2uv(uv)->v); /* remark upvalue's value */ |
| 335 | } | 343 | } |
| 336 | } | 344 | } |
| 337 | } | 345 | } |
| @@ -486,7 +494,7 @@ static int traverseproto (global_State *g, Proto *f) { | |||
| 486 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { | 494 | static lu_mem traverseCclosure (global_State *g, CClosure *cl) { |
| 487 | int i; | 495 | int i; |
| 488 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | 496 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ |
| 489 | markvalue(g, &cl->upvalue[i]); | 497 | marklocalvalue(g, &cl->upvalue[i]); |
| 490 | return sizeCclosure(cl->nupvalues); | 498 | return sizeCclosure(cl->nupvalues); |
| 491 | } | 499 | } |
| 492 | 500 | ||
| @@ -494,7 +502,7 @@ static lu_mem traverseLclosure (global_State *g, LClosure *cl) { | |||
| 494 | int i; | 502 | int i; |
| 495 | markobject(g, cl->p); /* mark its prototype */ | 503 | markobject(g, cl->p); /* mark its prototype */ |
| 496 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ | 504 | for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ |
| 497 | markobject(g, cl->upvals[i]); | 505 | marklocalobject(g, cl->upvals[i]); |
| 498 | return sizeLclosure(cl->nupvalues); | 506 | return sizeLclosure(cl->nupvalues); |
| 499 | } | 507 | } |
| 500 | 508 | ||
| @@ -505,7 +513,7 @@ static lu_mem traversestack (global_State *g, lua_State *th) { | |||
| 505 | if (o == NULL) | 513 | if (o == NULL) |
| 506 | return 1; /* stack not completely built yet */ | 514 | return 1; /* stack not completely built yet */ |
| 507 | for (; o < th->top; o++) /* mark live elements in the stack */ | 515 | for (; o < th->top; o++) /* mark live elements in the stack */ |
| 508 | markvalue(g, o); | 516 | marklocalvalue(g, o); |
| 509 | if (g->gcstate == GCSatomic) { /* final traversal? */ | 517 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
| 510 | StkId lim = th->stack + th->stacksize; /* real end of stack */ | 518 | StkId lim = th->stack + th->stacksize; /* real end of stack */ |
| 511 | for (; o < lim; o++) /* clear not-marked stack slice */ | 519 | for (; o < lim; o++) /* clear not-marked stack slice */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 2.59 2013/08/05 16:58:28 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.60 2013/08/13 17:36:44 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 | */ |
| @@ -79,6 +79,7 @@ | |||
| 79 | #define FINALIZEDBIT 3 /* object has been separated for finalization */ | 79 | #define FINALIZEDBIT 3 /* object has been separated for finalization */ |
| 80 | #define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ | 80 | #define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ |
| 81 | #define FIXEDBIT 5 /* object is fixed (should not be collected) */ | 81 | #define FIXEDBIT 5 /* object is fixed (should not be collected) */ |
| 82 | #define LOCALBIT 6 /* object is not local */ | ||
| 82 | /* bit 7 is currently used by tests (luaL_checkmemory) */ | 83 | /* bit 7 is currently used by tests (luaL_checkmemory) */ |
| 83 | 84 | ||
| 84 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) | 85 | #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) |
| @@ -88,6 +89,7 @@ | |||
| 88 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) | 89 | #define isblack(x) testbit((x)->gch.marked, BLACKBIT) |
| 89 | #define isgray(x) /* neither white nor black */ \ | 90 | #define isgray(x) /* neither white nor black */ \ |
| 90 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) | 91 | (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) |
| 92 | #define islocal(x) (!testbit((x)->gch.marked, LOCALBIT)) | ||
| 91 | 93 | ||
| 92 | 94 | ||
| 93 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) | 95 | #define otherwhite(g) (g->currentwhite ^ WHITEBITS) |
| @@ -97,6 +99,9 @@ | |||
| 97 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) | 99 | #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) |
| 98 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) | 100 | #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) |
| 99 | 101 | ||
| 102 | #define nolocal(x) l_setbit((x)->gch.marked, LOCALBIT) | ||
| 103 | #define valnolocal(v) { if (iscollectable(v)) nolocal(gcvalue(v)); } | ||
| 104 | |||
| 100 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) | 105 | #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) |
| 101 | 106 | ||
| 102 | 107 | ||
| @@ -106,22 +111,25 @@ | |||
| 106 | 111 | ||
| 107 | 112 | ||
| 108 | #define luaC_barrier(L,p,v) { \ | 113 | #define luaC_barrier(L,p,v) { \ |
| 109 | if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ | 114 | if (iscollectable(v) && \ |
| 115 | (nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \ | ||
| 110 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } | 116 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } |
| 111 | 117 | ||
| 112 | #define luaC_barrierback(L,p,v) { \ | 118 | #define luaC_barrierback(L,p,v) { \ |
| 113 | if (iscollectable(v) && isblack(obj2gco(p)) && iswhite(gcvalue(v))) \ | 119 | if (iscollectable(v) && \ |
| 120 | (nolocal(gcvalue(v)), isblack(obj2gco(p)) && iswhite(gcvalue(v)))) \ | ||
| 114 | luaC_barrierback_(L,p); } | 121 | luaC_barrierback_(L,p); } |
| 115 | 122 | ||
| 116 | #define luaC_objbarrier(L,p,o) { \ | 123 | #define luaC_objbarrier(L,p,o) { \ |
| 117 | if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ | 124 | if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ |
| 118 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } | 125 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } |
| 119 | 126 | ||
| 120 | #define luaC_objbarrierback(L,p,o) \ | 127 | #define luaC_objbarrierback(L,p,o) \ |
| 121 | { if (isblack(obj2gco(p)) && iswhite(obj2gco(o))) luaC_barrierback_(L,p); } | 128 | { if (nolocal(obj2gco(o)), isblack(obj2gco(p)) && iswhite(obj2gco(o))) \ |
| 129 | luaC_barrierback_(L,p); } | ||
| 122 | 130 | ||
| 123 | #define luaC_barrierproto(L,p,c) \ | 131 | #define luaC_barrierproto(L,p,c) \ |
| 124 | { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } | 132 | { if (nolocal(obj2gco(c)), isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } |
| 125 | 133 | ||
| 126 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); | 134 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); |
| 127 | LUAI_FUNC void luaC_step (lua_State *L); | 135 | LUAI_FUNC void luaC_step (lua_State *L); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 2.132 2013/04/25 19:35:19 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -1632,6 +1632,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | |||
| 1632 | incr_top(L); | 1632 | incr_top(L); |
| 1633 | funcstate.f = cl->l.p = luaF_newproto(L); | 1633 | funcstate.f = cl->l.p = luaF_newproto(L); |
| 1634 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ | 1634 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ |
| 1635 | luaC_objbarrier(L, funcstate.f, funcstate.f->source); | ||
| 1635 | lexstate.buff = buff; | 1636 | lexstate.buff = buff; |
| 1636 | lexstate.dyd = dyd; | 1637 | lexstate.dyd = dyd; |
| 1637 | dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; | 1638 | dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.c,v 2.100 2013/08/05 16:58:28 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.101 2013/08/07 12:18:11 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 | */ |
| @@ -159,17 +159,19 @@ static void freestack (lua_State *L) { | |||
| 159 | ** Create registry table and its predefined values | 159 | ** Create registry table and its predefined values |
| 160 | */ | 160 | */ |
| 161 | static void init_registry (lua_State *L, global_State *g) { | 161 | static void init_registry (lua_State *L, global_State *g) { |
| 162 | TValue mt; | 162 | TValue temp; |
| 163 | /* create registry */ | 163 | /* create registry */ |
| 164 | Table *registry = luaH_new(L); | 164 | Table *registry = luaH_new(L); |
| 165 | sethvalue(L, &g->l_registry, registry); | 165 | sethvalue(L, &g->l_registry, registry); |
| 166 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); | 166 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); |
| 167 | nolocal(obj2gco(registry)); | ||
| 167 | /* registry[LUA_RIDX_MAINTHREAD] = L */ | 168 | /* registry[LUA_RIDX_MAINTHREAD] = L */ |
| 168 | setthvalue(L, &mt, L); | 169 | setthvalue(L, &temp, L); /* temp = L */ |
| 169 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); | 170 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); |
| 170 | /* registry[LUA_RIDX_GLOBALS] = table of globals */ | 171 | /* registry[LUA_RIDX_GLOBALS] = table of globals */ |
| 171 | sethvalue(L, &mt, luaH_new(L)); | 172 | sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ |
| 172 | luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); | 173 | luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); |
| 174 | valnolocal(&temp); /* keep local invariant */ | ||
| 173 | } | 175 | } |
| 174 | 176 | ||
| 175 | 177 | ||
| @@ -236,6 +238,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { | |||
| 236 | setthvalue(L, L->top, L1); | 238 | setthvalue(L, L->top, L1); |
| 237 | api_incr_top(L); | 239 | api_incr_top(L); |
| 238 | preinit_state(L1, G(L)); | 240 | preinit_state(L1, G(L)); |
| 241 | nolocal(obj2gco(L1)); /* threads are never local */ | ||
| 239 | L1->hookmask = L->hookmask; | 242 | L1->hookmask = L->hookmask; |
| 240 | L1->basehookcount = L->basehookcount; | 243 | L1->basehookcount = L->basehookcount; |
| 241 | L1->hook = L->hook; | 244 | L1->hook = L->hook; |
| @@ -268,7 +271,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { | |||
| 268 | L->next = NULL; | 271 | L->next = NULL; |
| 269 | L->tt = LUA_TTHREAD; | 272 | L->tt = LUA_TTHREAD; |
| 270 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); | 273 | g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); |
| 271 | L->marked = luaC_white(g); | 274 | L->marked = luaC_white(g) | bitmask(LOCALBIT); |
| 272 | g->gckind = KGC_NORMAL; | 275 | g->gckind = KGC_NORMAL; |
| 273 | preinit_state(L, g); | 276 | preinit_state(L, g); |
| 274 | g->frealloc = f; | 277 | g->frealloc = f; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.h,v 1.48 2012/01/25 21:05:40 roberto Exp roberto $ | 2 | ** $Id: lstring.h,v 1.49 2012/02/01 21:57:15 roberto Exp roberto $ |
| 3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -19,7 +19,7 @@ | |||
| 19 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ | 19 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ |
| 20 | (sizeof(s)/sizeof(char))-1)) | 20 | (sizeof(s)/sizeof(char))-1)) |
| 21 | 21 | ||
| 22 | #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) | 22 | #define luaS_fix(s) setbits((s)->tsv.marked, bit2mask(FIXEDBIT, LOCALBIT)) |
| 23 | 23 | ||
| 24 | 24 | ||
| 25 | /* | 25 | /* |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 2.140 2013/08/05 16:58:28 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.141 2013/08/07 12:18:11 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 | */ |
| @@ -188,6 +188,25 @@ static int testobjref1 (global_State *g, GCObject *f, GCObject *t) { | |||
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | 190 | ||
| 191 | /* | ||
| 192 | ** Check locality | ||
| 193 | */ | ||
| 194 | static int testobjref2 (GCObject *f, GCObject *t) { | ||
| 195 | /* not a local or pointed by a thread? */ | ||
| 196 | if (!islocal(t) || gch(f)->tt == LUA_TTHREAD) | ||
| 197 | return 1; /* ok */ | ||
| 198 | if (gch(t)->tt == LUA_TUPVAL) { | ||
| 199 | lua_assert(gch(f)->tt == LUA_TLCL); | ||
| 200 | return 1; /* upvalue pointed by a closure */ | ||
| 201 | } | ||
| 202 | if (gch(f)->tt == LUA_TUPVAL) { | ||
| 203 | UpVal *uv = gco2uv(f); | ||
| 204 | return (uv->v != &uv->value); /* open upvalue can point to local stuff */ | ||
| 205 | } | ||
| 206 | return 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | |||
| 191 | static void printobj (global_State *g, GCObject *o) { | 210 | static void printobj (global_State *g, GCObject *o) { |
| 192 | int i = 1; | 211 | int i = 1; |
| 193 | GCObject *p; | 212 | GCObject *p; |
| @@ -198,24 +217,30 @@ static void printobj (global_State *g, GCObject *o) { | |||
| 198 | if (p == NULL) i = 0; /* zero means 'not found' */ | 217 | if (p == NULL) i = 0; /* zero means 'not found' */ |
| 199 | else i = -i; /* negative means 'found in findobj list */ | 218 | else i = -i; /* negative means 'found in findobj list */ |
| 200 | } | 219 | } |
| 201 | printf("||%d:%s(%p)-%c(%02X)||", i, ttypename(gch(o)->tt), (void *)o, | 220 | printf("||%d:%s(%p)-%s-%c(%02X)||", |
| 221 | i, ttypename(novariant(gch(o)->tt)), (void *)o, | ||
| 222 | islocal(o)?"L":"NL", | ||
| 202 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); | 223 | isdead(g,o)?'d':isblack(o)?'b':iswhite(o)?'w':'g', gch(o)->marked); |
| 203 | } | 224 | } |
| 204 | 225 | ||
| 205 | 226 | ||
| 206 | static int testobjref (global_State *g, GCObject *f, GCObject *t) { | 227 | static int testobjref (global_State *g, GCObject *f, GCObject *t) { |
| 207 | int r = testobjref1(g,f,t); | 228 | int r1 = testobjref1(g,f,t); |
| 208 | if (!r) { | 229 | int r2 = testobjref2(f,t); |
| 209 | printf("%d(%02X) - ", g->gcstate, g->currentwhite); | 230 | if (!r1 || !r2) { |
| 231 | if (!r1) | ||
| 232 | printf("%d(%02X) - ", g->gcstate, g->currentwhite); | ||
| 233 | else | ||
| 234 | printf("local violation - "); | ||
| 210 | printobj(g, f); | 235 | printobj(g, f); |
| 211 | printf("\t-> "); | 236 | printf(" -> "); |
| 212 | printobj(g, t); | 237 | printobj(g, t); |
| 213 | printf("\n"); | 238 | printf("\n"); |
| 214 | } | 239 | } |
| 215 | return r; | 240 | return r1 && r2; |
| 216 | } | 241 | } |
| 217 | 242 | ||
| 218 | #define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t))) | 243 | #define checkobjref(g,f,t) lua_assert(testobjref(g,f,obj2gco(t))) |
| 219 | 244 | ||
| 220 | 245 | ||
| 221 | static void checkvalref (global_State *g, GCObject *f, const TValue *t) { | 246 | static void checkvalref (global_State *g, GCObject *f, const TValue *t) { |
| @@ -349,6 +374,7 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { | |||
| 349 | break; | 374 | break; |
| 350 | } | 375 | } |
| 351 | case LUA_TTHREAD: { | 376 | case LUA_TTHREAD: { |
| 377 | lua_assert(!islocal(o)); | ||
| 352 | checkstack(g, gco2th(o)); | 378 | checkstack(g, gco2th(o)); |
| 353 | break; | 379 | break; |
| 354 | } | 380 | } |
| @@ -617,22 +643,9 @@ static int get_gccolor (lua_State *L) { | |||
| 617 | o = obj_at(L, 1); | 643 | o = obj_at(L, 1); |
| 618 | if (!iscollectable(o)) | 644 | if (!iscollectable(o)) |
| 619 | lua_pushstring(L, "no collectable"); | 645 | lua_pushstring(L, "no collectable"); |
| 620 | else { | 646 | else |
| 621 | int marked = gcvalue(o)->gch.marked; | ||
| 622 | int n = 1; | ||
| 623 | lua_pushstring(L, iswhite(gcvalue(o)) ? "white" : | 647 | lua_pushstring(L, iswhite(gcvalue(o)) ? "white" : |
| 624 | isblack(gcvalue(o)) ? "black" : "grey"); | 648 | isblack(gcvalue(o)) ? "black" : "grey"); |
| 625 | if (testbit(marked, FINALIZEDBIT)) { | ||
| 626 | lua_pushliteral(L, "/finalized"); n++; | ||
| 627 | } | ||
| 628 | if (testbit(marked, SEPARATED)) { | ||
| 629 | lua_pushliteral(L, "/separated"); n++; | ||
| 630 | } | ||
| 631 | if (testbit(marked, FIXEDBIT)) { | ||
| 632 | lua_pushliteral(L, "/fixed"); n++; | ||
| 633 | } | ||
| 634 | lua_concat(L, n); | ||
| 635 | } | ||
| 636 | return 1; | 649 | return 1; |
| 637 | } | 650 | } |
| 638 | 651 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp roberto $ | 2 | ** $Id: lundump.c,v 2.23 2013/04/26 18:48:35 roberto Exp roberto $ |
| 3 | ** load precompiled Lua chunks | 3 | ** load precompiled Lua chunks |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -84,9 +84,12 @@ static TString* LoadString(LoadState* S) | |||
| 84 | return NULL; | 84 | return NULL; |
| 85 | else | 85 | else |
| 86 | { | 86 | { |
| 87 | TString* ts; | ||
| 87 | char* s=luaZ_openspace(S->L,S->b,size); | 88 | char* s=luaZ_openspace(S->L,S->b,size); |
| 88 | LoadBlock(S,s,size*sizeof(char)); | 89 | LoadBlock(S,s,size*sizeof(char)); |
| 89 | return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ | 90 | ts = luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ |
| 91 | nolocal(obj2gco(ts)); /* all strings here anchored in non-thread objects */ | ||
| 92 | return ts; | ||
| 90 | } | 93 | } |
| 91 | } | 94 | } |
| 92 | 95 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.175 2013/06/20 15:02:49 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.176 2013/07/10 17:15:12 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -416,6 +416,7 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, | |||
| 416 | ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); | 416 | ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); |
| 417 | else /* get upvalue from enclosing function */ | 417 | else /* get upvalue from enclosing function */ |
| 418 | ncl->l.upvals[i] = encup[uv[i].idx]; | 418 | ncl->l.upvals[i] = encup[uv[i].idx]; |
| 419 | /* new closure is white and local, so we do not need a barrier here */ | ||
| 419 | } | 420 | } |
| 420 | luaC_barrierproto(L, p, ncl); | 421 | luaC_barrierproto(L, p, ncl); |
| 421 | p->cache = ncl; /* save it on cache for reuse */ | 422 | p->cache = ncl; /* save it on cache for reuse */ |
