lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Roberto Ierusalimschy wrote:
> The bigest problem with this idea seems to be the "identification" of
> different functions into one. This seems rare, but may cause quite hard
> bugs. (Imagine the emulation of the old setfenv, using 'upvaluejoin',
> over such clones...)

I made an experimental patch for Lua 5.1 (since the idea works
there, too). And the setfenv() cases are exactly where it fails
the tests (it passes all other tests).

There is a significant speedup for the obvious test cases. E.g.
comparing a 100% cache miss vs. a 100% cache hit:

$ time lua-clc -e "local k; for i=1,1e7 do local function x() return i end end"
2.230
$ time lua-clc -e "local k; for i=1,1e7 do local function x() return k end end"
0.200

But ... I don't see any kind of speedup in real-world use cases.
Maybe that's because I carefully avoid creating closures in inner
loops. Anyway, I've attached the patch so others can play with it.

--Mike
--- lua-5.1.4/src/lobject.h	2008-08-06 15:29:48 +0200
+++ lua-5.1.4-clcache/src/lobject.h	2010-05-24 20:15:00 +0200
@@ -228,10 +228,12 @@
 /*
 ** Function Prototypes
 */
+union Closure;
 typedef struct Proto {
   CommonHeader;
   TValue *k;  /* constants used by the function */
   Instruction *code;
+  union Closure *clcache;
   struct Proto **p;  /* functions defined inside the function */
   int *lineinfo;  /* map from opcodes to source lines */
   struct LocVar *locvars;  /* information about local variables */
--- lua-5.1.4/src/lgc.c	2007-12-27 14:02:25 +0100
+++ lua-5.1.4-clcache/src/lgc.c	2010-05-24 20:15:00 +0200
@@ -202,6 +202,7 @@
 */
 static void traverseproto (global_State *g, Proto *f) {
   int i;
+  if (f->clcache && iswhite(obj2gco(f->clcache))) f->clcache = NULL;
   if (f->source) stringmark(f->source);
   for (i=0; i<f->sizek; i++)  /* mark literals */
     markvalue(g, &f->k[i]);
--- lua-5.1.4/src/lfunc.c	2007-12-28 15:58:43 +0100
+++ lua-5.1.4-clcache/src/lfunc.c	2010-05-24 20:15:00 +0200
@@ -123,6 +123,7 @@
   f->sizecode = 0;
   f->sizelineinfo = 0;
   f->sizeupvalues = 0;
+  f->clcache = NULL;
   f->nups = 0;
   f->upvalues = NULL;
   f->numparams = 0;
--- lua-5.1.4/src/lvm.c	2007-12-28 16:32:23 +0100
+++ lua-5.1.4-clcache/src/lvm.c	2010-05-24 20:15:00 +0200
@@ -722,6 +722,22 @@
         int nup, j;
         p = cl->p->p[GETARG_Bx(i)];
         nup = p->nups;
+        if (p->clcache) {
+          UpVal **uv = p->clcache->l.upvals;
+          for (j=0; j<nup; j++) {
+            if (GET_OPCODE(pc[j]) == OP_GETUPVAL) {
+              if (uv[j] != cl->upvals[GETARG_B(pc[j])])
+                goto newcl;
+            } else {
+              lua_assert(GET_OPCODE(pc[j]) == OP_MOVE);
+              if (uv[j]->v != base + GETARG_B(pc[j]))
+                goto newcl;
+            }
+          }
+          setclvalue(L, ra, p->clcache);
+          continue;
+        }
+      newcl:
         ncl = luaF_newLclosure(L, nup, cl->env);
         ncl->l.p = p;
         for (j=0; j<nup; j++, pc++) {
@@ -733,6 +749,8 @@
           }
         }
         setclvalue(L, ra, ncl);
+        p->clcache = ncl;
+        if (isblack(obj2gco(p))) luaC_barrierf(L, obj2gco(p), obj2gco(ncl));
         Protect(luaC_checkGC(L));
         continue;
       }