diff options
| -rw-r--r-- | lfunc.c | 7 | ||||
| -rw-r--r-- | lgc.c | 50 | ||||
| -rw-r--r-- | lgc.h | 22 | ||||
| -rw-r--r-- | lobject.h | 3 | ||||
| -rw-r--r-- | lvm.c | 68 |
5 files changed, 114 insertions, 36 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lfunc.c,v 2.23 2010/04/29 21:43:36 roberto Exp roberto $ | 2 | ** $Id: lfunc.c,v 2.24 2010/05/10 18:23:45 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,9 +29,11 @@ Closure *luaF_newCclosure (lua_State *L, int n) { | |||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | 31 | ||
| 32 | Closure *luaF_newLclosure (lua_State *L, int n) { | 32 | Closure *luaF_newLclosure (lua_State *L, Proto *p) { |
| 33 | int n = p->sizeupvalues; | ||
| 33 | Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeLclosure(n), NULL, 0)->cl; | 34 | Closure *c = &luaC_newobj(L, LUA_TFUNCTION, sizeLclosure(n), NULL, 0)->cl; |
| 34 | c->l.isC = 0; | 35 | c->l.isC = 0; |
| 36 | c->l.p = p; | ||
| 35 | c->l.nupvalues = cast_byte(n); | 37 | c->l.nupvalues = cast_byte(n); |
| 36 | while (n--) c->l.upvals[n] = NULL; | 38 | while (n--) c->l.upvals[n] = NULL; |
| 37 | return c; | 39 | return c; |
| @@ -116,6 +118,7 @@ Proto *luaF_newproto (lua_State *L) { | |||
| 116 | f->p = NULL; | 118 | f->p = NULL; |
| 117 | f->sizep = 0; | 119 | f->sizep = 0; |
| 118 | f->code = NULL; | 120 | f->code = NULL; |
| 121 | f->cache = NULL; | ||
| 119 | f->sizecode = 0; | 122 | f->sizecode = 0; |
| 120 | f->lineinfo = NULL; | 123 | f->lineinfo = NULL; |
| 121 | f->sizelineinfo = 0; | 124 | f->sizelineinfo = 0; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.96 2010/05/17 20:39:31 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.97 2010/06/02 18:36:58 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 | */ |
| @@ -127,7 +127,7 @@ static int iscleared (const TValue *o, int iskey) { | |||
| 127 | ** barrier that moves collector forward, that is, mark the white object | 127 | ** barrier that moves collector forward, that is, mark the white object |
| 128 | ** being pointed by a black object. | 128 | ** being pointed by a black object. |
| 129 | */ | 129 | */ |
| 130 | void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | 130 | void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { |
| 131 | global_State *g = G(L); | 131 | global_State *g = G(L); |
| 132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); | 132 | lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); |
| 133 | lua_assert(isgenerational(g) || g->gcstate != GCSpause); | 133 | lua_assert(isgenerational(g) || g->gcstate != GCSpause); |
| @@ -143,19 +143,32 @@ void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { | |||
| 143 | 143 | ||
| 144 | /* | 144 | /* |
| 145 | ** barrier that moves collector backward, that is, mark the black object | 145 | ** barrier that moves collector backward, that is, mark the black object |
| 146 | ** pointing to a white object as gray again. | 146 | ** pointing to a white object as gray again. (Current implementation |
| 147 | ** only works for tables; access to 'gclist' is not uniform across | ||
| 148 | ** different types.) | ||
| 147 | */ | 149 | */ |
| 148 | void luaC_barrierback (lua_State *L, Table *t) { | 150 | void luaC_barrierback_ (lua_State *L, GCObject *o) { |
| 149 | global_State *g = G(L); | 151 | global_State *g = G(L); |
| 150 | GCObject *o = obj2gco(t); | ||
| 151 | lua_assert(isblack(o) && !isdead(g, o)); | 152 | lua_assert(isblack(o) && !isdead(g, o)); |
| 152 | black2gray(o); /* make table gray (again) */ | 153 | black2gray(o); /* make object gray (again) */ |
| 153 | t->gclist = g->grayagain; | 154 | gco2t(o)->gclist = g->grayagain; |
| 154 | g->grayagain = o; | 155 | g->grayagain = o; |
| 155 | } | 156 | } |
| 156 | 157 | ||
| 157 | 158 | ||
| 158 | /* | 159 | /* |
| 160 | ** barrier for prototypes | ||
| 161 | */ | ||
| 162 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, GCObject *p) { | ||
| 163 | global_State *g = G(L); | ||
| 164 | lua_assert(isblack(p)); | ||
| 165 | black2gray(p); /* make object gray (again) */ | ||
| 166 | gco2p(p)->gclist = g->clearcache; | ||
| 167 | g->clearcache = p; | ||
| 168 | } | ||
| 169 | |||
| 170 | |||
| 171 | /* | ||
| 159 | ** check color (and invariants) for an upvalue that was closed, | 172 | ** check color (and invariants) for an upvalue that was closed, |
| 160 | ** i.e., moved into the 'allgc' list | 173 | ** i.e., moved into the 'allgc' list |
| 161 | */ | 174 | */ |
| @@ -299,7 +312,7 @@ static void remarkupvals (global_State *g) { | |||
| 299 | static void markroot (lua_State *L) { | 312 | static void markroot (lua_State *L) { |
| 300 | global_State *g = G(L); | 313 | global_State *g = G(L); |
| 301 | g->gray = g->grayagain = NULL; | 314 | g->gray = g->grayagain = NULL; |
| 302 | g->weak = g->allweak = g->ephemeron = NULL; | 315 | g->weak = g->allweak = g->ephemeron = g->clearcache = NULL; |
| 303 | markobject(g, g->mainthread); | 316 | markobject(g, g->mainthread); |
| 304 | markvalue(g, &g->l_registry); | 317 | markvalue(g, &g->l_registry); |
| 305 | markmt(g); | 318 | markmt(g); |
| @@ -409,8 +422,19 @@ static int traversetable (global_State *g, Table *h) { | |||
| 409 | } | 422 | } |
| 410 | 423 | ||
| 411 | 424 | ||
| 425 | /* | ||
| 426 | ** if prototype's cached closure is not marked, erase it so it | ||
| 427 | ** can be collected | ||
| 428 | */ | ||
| 429 | static void checkcache (Proto *p) { | ||
| 430 | if (p->cache && iswhite(obj2gco(p->cache))) | ||
| 431 | p->cache = NULL; /* allow cache to be collected */ | ||
| 432 | } | ||
| 433 | |||
| 434 | |||
| 412 | static int traverseproto (global_State *g, Proto *f) { | 435 | static int traverseproto (global_State *g, Proto *f) { |
| 413 | int i; | 436 | int i; |
| 437 | checkcache(f); | ||
| 414 | stringmark(f->source); | 438 | stringmark(f->source); |
| 415 | for (i = 0; i < f->sizek; i++) /* mark literals */ | 439 | for (i = 0; i < f->sizek; i++) /* mark literals */ |
| 416 | markvalue(g, &f->k[i]); | 440 | markvalue(g, &f->k[i]); |
| @@ -534,6 +558,15 @@ static void convergeephemerons (global_State *g) { | |||
| 534 | */ | 558 | */ |
| 535 | 559 | ||
| 536 | /* | 560 | /* |
| 561 | ** clear cache field in all prototypes in list 'l' | ||
| 562 | */ | ||
| 563 | static void clearproto (GCObject *l) { | ||
| 564 | for (; l != NULL; l = gco2p(l)->gclist) | ||
| 565 | checkcache(gco2p(l)); | ||
| 566 | } | ||
| 567 | |||
| 568 | |||
| 569 | /* | ||
| 537 | ** clear collected entries from all weaktables in list 'l' | 570 | ** clear collected entries from all weaktables in list 'l' |
| 538 | */ | 571 | */ |
| 539 | static void cleartable (GCObject *l) { | 572 | static void cleartable (GCObject *l) { |
| @@ -845,6 +878,7 @@ static void atomic (lua_State *L) { | |||
| 845 | cleartable(g->weak); | 878 | cleartable(g->weak); |
| 846 | cleartable(g->ephemeron); | 879 | cleartable(g->ephemeron); |
| 847 | cleartable(g->allweak); | 880 | cleartable(g->allweak); |
| 881 | clearproto(g->clearcache); | ||
| 848 | g->sweepstrgc = 0; /* prepare to sweep strings */ | 882 | g->sweepstrgc = 0; /* prepare to sweep strings */ |
| 849 | g->gcstate = GCSsweepstring; | 883 | g->gcstate = GCSsweepstring; |
| 850 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ | 884 | g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.h,v 2.40 2010/05/10 16:46:49 roberto Exp roberto $ | 2 | ** $Id: lgc.h,v 2.41 2010/05/10 18:23:45 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 | */ |
| @@ -112,17 +112,20 @@ | |||
| 112 | 112 | ||
| 113 | 113 | ||
| 114 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ | 114 | #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ |
| 115 | luaC_barrierf(L,obj2gco(p),gcvalue(v)); } | 115 | luaC_barrier_(L,obj2gco(p),gcvalue(v)); } |
| 116 | 116 | ||
| 117 | #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ | 117 | #define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ |
| 118 | luaC_barrierback(L,t); } | 118 | luaC_barrierback_(L,p); } |
| 119 | 119 | ||
| 120 | #define luaC_objbarrier(L,p,o) \ | 120 | #define luaC_objbarrier(L,p,o) \ |
| 121 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ | 121 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ |
| 122 | luaC_barrierf(L,obj2gco(p),obj2gco(o)); } | 122 | luaC_barrier_(L,obj2gco(p),obj2gco(o)); } |
| 123 | 123 | ||
| 124 | #define luaC_objbarriert(L,t,o) \ | 124 | #define luaC_objbarrierback(L,p,o) \ |
| 125 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } | 125 | { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } |
| 126 | |||
| 127 | #define luaC_barrierproto(L,p) \ | ||
| 128 | { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p); } | ||
| 126 | 129 | ||
| 127 | LUAI_FUNC void luaC_separateudata (lua_State *L, int all); | 130 | LUAI_FUNC void luaC_separateudata (lua_State *L, int all); |
| 128 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); | 131 | LUAI_FUNC void luaC_freeallobjects (lua_State *L); |
| @@ -131,8 +134,9 @@ LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); | |||
| 131 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); | 134 | LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); |
| 132 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, | 135 | LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, |
| 133 | GCObject **list, int offset); | 136 | GCObject **list, int offset); |
| 134 | LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); | 137 | LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); |
| 135 | LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); | 138 | LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); |
| 139 | LUAI_FUNC void luaC_barrierproto_ (lua_State *L, GCObject *p); | ||
| 136 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u); | 140 | LUAI_FUNC void luaC_checkfinalizer (lua_State *L, Udata *u); |
| 137 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); | 141 | LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); |
| 138 | LUAI_FUNC void luaC_changemode (lua_State *L, int mode); | 142 | LUAI_FUNC void luaC_changemode (lua_State *L, int mode); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.39 2010/04/18 13:22:48 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.40 2010/05/07 18:44:46 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -266,6 +266,7 @@ typedef struct Proto { | |||
| 266 | int *lineinfo; /* map from opcodes to source lines */ | 266 | int *lineinfo; /* map from opcodes to source lines */ |
| 267 | struct LocVar *locvars; /* information about local variables */ | 267 | struct LocVar *locvars; /* information about local variables */ |
| 268 | Upvaldesc *upvalues; /* upvalue information */ | 268 | Upvaldesc *upvalues; /* upvalue information */ |
| 269 | union Closure *cache; /* last created closure with this prototype */ | ||
| 269 | TString *source; | 270 | TString *source; |
| 270 | int sizeupvalues; /* size of 'upvalues' */ | 271 | int sizeupvalues; /* size of 'upvalues' */ |
| 271 | int sizek; /* size of `k' */ | 272 | int sizek; /* size of `k' */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.119 2010/05/12 20:40:35 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.120 2010/05/13 19:53:05 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 | */ |
| @@ -136,7 +136,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
| 136 | if (!ttisnil(oldval) || /* result is not nil? */ | 136 | if (!ttisnil(oldval) || /* result is not nil? */ |
| 137 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ | 137 | (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ |
| 138 | setobj2t(L, oldval, val); | 138 | setobj2t(L, oldval, val); |
| 139 | luaC_barriert(L, h, val); | 139 | luaC_barrierback(L, obj2gco(h), val); |
| 140 | return; | 140 | return; |
| 141 | } | 141 | } |
| 142 | /* else will try the tag method */ | 142 | /* else will try the tag method */ |
| @@ -346,6 +346,49 @@ void luaV_arith (lua_State *L, StkId ra, const TValue *rb, | |||
| 346 | 346 | ||
| 347 | 347 | ||
| 348 | /* | 348 | /* |
| 349 | ** check whether cached closure in prototype 'p' may be reused, that is, | ||
| 350 | ** whether there is a cached closure with the same upvalues needed by | ||
| 351 | ** new closure to be created. | ||
| 352 | */ | ||
| 353 | static Closure *getcached (Proto *p, UpVal **encup, StkId base) { | ||
| 354 | Closure *c = p->cache; | ||
| 355 | if (c != NULL) { /* is there a cached closure? */ | ||
| 356 | int nup = p->sizeupvalues; | ||
| 357 | Upvaldesc *uv = p->upvalues; | ||
| 358 | int i; | ||
| 359 | for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ | ||
| 360 | TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; | ||
| 361 | if (c->l.upvals[i]->v != v) | ||
| 362 | return NULL; /* wrong upvalue; cannot reuse closure */ | ||
| 363 | } | ||
| 364 | } | ||
| 365 | return c; /* return cached closure (or NULL if no cached closure) */ | ||
| 366 | } | ||
| 367 | |||
| 368 | |||
| 369 | /* | ||
| 370 | ** create a new Lua closure, push it in the stack, and initialize | ||
| 371 | ** its upvalues | ||
| 372 | */ | ||
| 373 | static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, | ||
| 374 | StkId ra) { | ||
| 375 | int nup = p->sizeupvalues; | ||
| 376 | Upvaldesc *uv = p->upvalues; | ||
| 377 | int i; | ||
| 378 | Closure *ncl = luaF_newLclosure(L, p); | ||
| 379 | setclvalue(L, ra, ncl); /* anchor new closure in stack */ | ||
| 380 | for (i = 0; i < nup; i++) { /* fill in its upvalues */ | ||
| 381 | if (uv[i].instack) /* upvalue refers to local variable? */ | ||
| 382 | ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); | ||
| 383 | else /* get upvalue from enclosing function */ | ||
| 384 | ncl->l.upvals[i] = encup[uv[i].idx]; | ||
| 385 | } | ||
| 386 | p->cache = ncl; /* save it on cache, so it can be reused */ | ||
| 387 | luaC_barrierproto(L, obj2gco(p)); | ||
| 388 | } | ||
| 389 | |||
| 390 | |||
| 391 | /* | ||
| 349 | ** finish execution of an opcode interrupted by an yield | 392 | ** finish execution of an opcode interrupted by an yield |
| 350 | */ | 393 | */ |
| 351 | void luaV_finishOp (lua_State *L) { | 394 | void luaV_finishOp (lua_State *L) { |
| @@ -721,7 +764,7 @@ void luaV_execute (lua_State *L) { | |||
| 721 | for (; n > 0; n--) { | 764 | for (; n > 0; n--) { |
| 722 | TValue *val = ra+n; | 765 | TValue *val = ra+n; |
| 723 | setobj2t(L, luaH_setint(L, h, last--), val); | 766 | setobj2t(L, luaH_setint(L, h, last--), val); |
| 724 | luaC_barriert(L, h, val); | 767 | luaC_barrierback(L, obj2gco(h), val); |
| 725 | } | 768 | } |
| 726 | L->top = ci->top; /* correct top (in case of previous open call) */ | 769 | L->top = ci->top; /* correct top (in case of previous open call) */ |
| 727 | ) | 770 | ) |
| @@ -729,19 +772,12 @@ void luaV_execute (lua_State *L) { | |||
| 729 | luaF_close(L, ra); | 772 | luaF_close(L, ra); |
| 730 | ) | 773 | ) |
| 731 | vmcase(OP_CLOSURE, | 774 | vmcase(OP_CLOSURE, |
| 732 | Proto *p = cl->p->p[GETARG_Bx(i)]; /* prototype for new closure */ | 775 | Proto *p = cl->p->p[GETARG_Bx(i)]; |
| 733 | int nup = p->sizeupvalues; | 776 | Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ |
| 734 | Closure *ncl = luaF_newLclosure(L, nup); | 777 | if (ncl == NULL) /* no match? */ |
| 735 | Upvaldesc *uv = p->upvalues; | 778 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ |
| 736 | int j; | 779 | else |
| 737 | ncl->l.p = p; | 780 | setclvalue(L, ra, ncl); /* push cashed closure */ |
| 738 | setclvalue(L, ra, ncl); /* anchor new closure in stack */ | ||
| 739 | for (j = 0; j < nup; j++) { /* fill in upvalues */ | ||
| 740 | if (uv[j].instack) /* upvalue refers to local variable? */ | ||
| 741 | ncl->l.upvals[j] = luaF_findupval(L, base + uv[j].idx); | ||
| 742 | else /* get upvalue from enclosing function */ | ||
| 743 | ncl->l.upvals[j] = cl->upvals[uv[j].idx]; | ||
| 744 | } | ||
| 745 | checkGC(L); | 781 | checkGC(L); |
| 746 | ) | 782 | ) |
| 747 | vmcase(OP_VARARG, | 783 | vmcase(OP_VARARG, |
