aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-06-04 10:25:10 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2010-06-04 10:25:10 -0300
commit575074fd857b90cd7c14c7b172e8fe147080962a (patch)
tree6929e87845a56266061235f89213795806ee5291 /lvm.c
parent545f43065ff8fa20e5f8254e6270d00694b847dd (diff)
downloadlua-575074fd857b90cd7c14c7b172e8fe147080962a.tar.gz
lua-575074fd857b90cd7c14c7b172e8fe147080962a.tar.bz2
lua-575074fd857b90cd7c14c7b172e8fe147080962a.zip
Lua closures are cached for reuse
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c68
1 files changed, 52 insertions, 16 deletions
diff --git a/lvm.c b/lvm.c
index ce0572f3..3a66e0aa 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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*/
353static 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*/
373static 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*/
351void luaV_finishOp (lua_State *L) { 394void 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,