diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-01 13:21:00 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-01 13:21:00 -0300 |
commit | e8c779736f3029df353038352c14c8ab63728811 (patch) | |
tree | 23f75fa455ec333677650198cd889b187228b735 /lvm.c | |
parent | 2fc6b55dae7a120b4272ca0e9c356d1f96053bd9 (diff) | |
download | lua-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.c | 39 |
1 files changed, 2 insertions, 37 deletions
@@ -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 | */ | ||
691 | static 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 | */ |
712 | static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, | 690 | static 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 | } |