summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
authorMike Pall <mike>2011-11-20 19:14:39 +0100
committerMike Pall <mike>2011-11-20 19:16:40 +0100
commitcecbe3c15fc62921098f3468b9de86cf0b631b9e (patch)
treed1b18c59652a3e163ce050e58b7b647fdf312271 /src/lj_record.c
parentcc7a12be93660677a5128124c11c68127cfe33eb (diff)
downloadluajit2-cecbe3c15fc62921098f3468b9de86cf0b631b9e.tar.gz
Specialize to prototype for non-monomorphic functions.
Solves the trace-explosion problem with closure-heavy programming.
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 61e09b6d..a76f5d94 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -563,12 +563,32 @@ static void rec_loop_jit(jit_State *J, TraceNo lnk, LoopEvent ev)
/* -- Record calls and returns -------------------------------------------- */
+/* Specialize to the runtime value of the called function or its prototype. */
+static TRef rec_call_specialize(jit_State *J, GCfunc *fn, TRef tr)
+{
+ TRef kfunc;
+ if (isluafunc(fn)) {
+ GCproto *pt = funcproto(fn);
+ /* 3 or more closures created? Probably not a monomorphic function. */
+ if (pt->flags >= 3*PROTO_CLCOUNT) { /* Specialize to prototype instead. */
+ TRef trpt = emitir(IRT(IR_FLOAD, IRT_P32), tr, IRFL_FUNC_PC);
+ emitir(IRTG(IR_EQ, IRT_P32), trpt, lj_ir_kptr(J, proto_bc(pt)));
+ (void)lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); /* Prevent GC of proto. */
+ return tr;
+ }
+ }
+ /* Otherwise specialize to the function (closure) value itself. */
+ kfunc = lj_ir_kfunc(J, fn);
+ emitir(IRTG(IR_EQ, IRT_FUNC), tr, kfunc);
+ return kfunc;
+}
+
/* Record call setup. */
static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs)
{
RecordIndex ix;
TValue *functv = &J->L->base[func];
- TRef trfunc, *fbase = &J->base[func];
+ TRef *fbase = &J->base[func];
ptrdiff_t i;
for (i = 0; i <= nargs; i++)
(void)getslot(J, func+i); /* Ensure func and all args have a reference. */
@@ -582,11 +602,7 @@ static void rec_call_setup(jit_State *J, BCReg func, ptrdiff_t nargs)
fbase[0] = ix.mobj; /* Replace function. */
functv = &ix.mobjv;
}
-
- /* Specialize to the runtime value of the called function. */
- trfunc = lj_ir_kfunc(J, funcV(functv));
- emitir(IRTG(IR_EQ, IRT_FUNC), fbase[0], trfunc);
- fbase[0] = trfunc | TREF_FRAME;
+ fbase[0] = TREF_FRAME | rec_call_specialize(J, funcV(functv), fbase[0]);
J->maxslot = (BCReg)nargs;
}