aboutsummaryrefslogtreecommitdiff
path: root/lvm.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-01 13:21:00 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-11-01 13:21:00 -0300
commite8c779736f3029df353038352c14c8ab63728811 (patch)
tree23f75fa455ec333677650198cd889b187228b735 /lvm.c
parent2fc6b55dae7a120b4272ca0e9c356d1f96053bd9 (diff)
downloadlua-e8c779736f3029df353038352c14c8ab63728811.tar.gz
lua-e8c779736f3029df353038352c14c8ab63728811.tar.bz2
lua-e8c779736f3029df353038352c14c8ab63728811.zip
Removed internal cache for closures
The mechanism of "caching the last closure created for a prototype to try to reuse it the next time a closure for that prototype is created" was removed. There are several reasons: - It is hard to find a natural example where this cache has a measurable impact on performance. - Programmers already perceive closure creation as something slow, so they tend to avoid it inside hot paths. (Any case where the cache could reuse a closure can be rewritten predefining the closure in some variable and using that variable.) - The implementation was somewhat complex, due to a bad interaction with the generational collector. (Typically, new closures are new, while prototypes are old. So, the cache breaks the invariant that old objects should not point to new ones.)
Diffstat (limited to 'lvm.c')
-rw-r--r--lvm.c39
1 files changed, 2 insertions, 37 deletions
diff --git a/lvm.c b/lvm.c
index 1535700f..d9671055 100644
--- a/lvm.c
+++ b/lvm.c
@@ -684,30 +684,8 @@ lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) {
684 684
685 685
686/* 686/*
687** check whether cached closure in prototype 'p' may be reused, that is,
688** whether there is a cached closure with the same upvalues needed by
689** new closure to be created.
690*/
691static LClosure *getcached (Proto *p, UpVal **encup, StkId base) {
692 LClosure *c = p->cache;
693 if (c != NULL) { /* is there a cached closure? */
694 int nup = p->sizeupvalues;
695 Upvaldesc *uv = p->upvalues;
696 int i;
697 for (i = 0; i < nup; i++) { /* check whether it has right upvalues */
698 TValue *v = uv[i].instack ? s2v(base + uv[i].idx) : encup[uv[i].idx]->v;
699 if (c->upvals[i]->v != v)
700 return NULL; /* wrong upvalue; cannot reuse closure */
701 }
702 p->cachemiss = 0; /* got a hit */
703 }
704 return c; /* return cached closure (or NULL if no cached closure) */
705}
706
707
708/*
709** create a new Lua closure, push it in the stack, and initialize 687** create a new Lua closure, push it in the stack, and initialize
710** its upvalues. ??? 688** its upvalues.
711*/ 689*/
712static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, 690static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
713 StkId ra) { 691 StkId ra) {
@@ -724,13 +702,6 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
724 ncl->upvals[i] = encup[uv[i].idx]; 702 ncl->upvals[i] = encup[uv[i].idx];
725 luaC_objbarrier(L, ncl, ncl->upvals[i]); 703 luaC_objbarrier(L, ncl, ncl->upvals[i]);
726 } 704 }
727 if (p->cachemiss >= MAXMISS) /* too many missings? */
728 p->cache = NULL; /* give up cache */
729 else {
730 p->cache = ncl; /* save it on cache for reuse */
731 luaC_protobarrier(L, p, ncl);
732 p->cachemiss++;
733 }
734} 705}
735 706
736 707
@@ -1811,13 +1782,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
1811 } 1782 }
1812 vmcase(OP_CLOSURE) { 1783 vmcase(OP_CLOSURE) {
1813 Proto *p = cl->p->p[GETARG_Bx(i)]; 1784 Proto *p = cl->p->p[GETARG_Bx(i)];
1814 LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ 1785 halfProtect(pushclosure(L, p, cl->upvals, base, ra));
1815 if (ncl == NULL) { /* no match? */
1816 savestate(L, ci); /* in case of allocation errors */
1817 pushclosure(L, p, cl->upvals, base, ra); /* create a new one */
1818 }
1819 else
1820 setclLvalue2s(L, ra, ncl); /* push cashed closure */
1821 checkGC(L, ra + 1); 1786 checkGC(L, ra + 1);
1822 vmbreak; 1787 vmbreak;
1823 } 1788 }