diff options
author | daurnimator <quae@daurnimator.com> | 2017-05-24 16:55:45 +1000 |
---|---|---|
committer | daurnimator <quae@daurnimator.com> | 2017-05-29 13:45:03 +1000 |
commit | 73d641f4cb9788757188ee1147c558bd07a16a93 (patch) | |
tree | 1277998c5573877c61531c3cfdd1a900cd8059fc /src/lvm.js | |
parent | 02bec8525e5dbdb9de0268d666af7511bb130e64 (diff) | |
download | fengari-73d641f4cb9788757188ee1147c558bd07a16a93.tar.gz fengari-73d641f4cb9788757188ee1147c558bd07a16a93.tar.bz2 fengari-73d641f4cb9788757188ee1147c558bd07a16a93.zip |
src/lvm.js: cache closures
Diffstat (limited to 'src/lvm.js')
-rw-r--r-- | src/lvm.js | 26 |
1 files changed, 25 insertions, 1 deletions
@@ -687,7 +687,11 @@ const luaV_execute = function(L) { } case OCi.OP_CLOSURE: { let p = cl.p.p[i.Bx]; - pushclosure(L, p, cl.upvals, base, ra); /* create a new one */ + let ncl = getcached(p, cl.upvals, L.stack, base); /* cached closure */ + if (ncl === null) /* no match? */ + pushclosure(L, p, cl.upvals, base, ra); /* create a new one */ + else + L.stack[ra].setclLvalue(ncl); break; } case OCi.OP_VARARG: { @@ -1024,6 +1028,25 @@ const luaV_shiftl = function(x, y) { }; /* +** check whether cached closure in prototype 'p' may be reused, that is, +** whether there is a cached closure with the same upvalues needed by +** new closure to be created. +*/ +const getcached = function(p, encup, stack, base) { + let c = p.cache; + if (c !== null) { /* is there a cached closure? */ + let uv = p.upvalues; + let nup = uv.length; + for (let i = 0; i < nup; i++) { /* check whether it has right upvalues */ + let v = uv[i].instack ? stack[base + uv[i].idx] : encup[uv[i].idx].v; + if (c.upvals[i].v !== v) + return null; /* wrong upvalue; cannot reuse closure */ + } + } + return c; /* return cached closure (or NULL if no cached closure) */ +}; + +/* ** create a new Lua closure, push it in the stack, and initialize ** its upvalues. */ @@ -1040,6 +1063,7 @@ const pushclosure = function(L, p, encup, base, ra) { ncl.upvals[i] = encup[uv[i].idx]; ncl.upvals[i].refcount++; } + p.cache = ncl; /* save it on cache for reuse */ }; const cvt2str = function(o) { |