diff options
author | Mike Pall <mike> | 2011-06-29 01:53:39 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-06-29 01:53:39 +0200 |
commit | 64dbe7d929cb5c368176ccb967b8909a4af8ede3 (patch) | |
tree | e0dcc6fef7ccca7d9b77e4f6c2364779956f499b /src | |
parent | 82eca898db87bde10fbbb14a0f35ef75b6c3dcc6 (diff) | |
download | luajit-64dbe7d929cb5c368176ccb967b8909a4af8ede3.tar.gz luajit-64dbe7d929cb5c368176ccb967b8909a4af8ede3.tar.bz2 luajit-64dbe7d929cb5c368176ccb967b8909a4af8ede3.zip |
Return to lower frame via interpreter for unhandled cases.
E.g. spontaneous upcalls from C are now compiled.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_record.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 49d743a2..e4c59bf4 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -661,6 +661,17 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
661 | J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ | 661 | J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */ |
662 | frame = frame_prevd(frame); | 662 | frame = frame_prevd(frame); |
663 | } | 663 | } |
664 | /* Return to lower frame via interpreter for unhandled cases. */ | ||
665 | if (J->framedepth == 0 && J->pt && bc_isret(bc_op(*J->pc)) && | ||
666 | (!frame_islua(frame) || | ||
667 | (J->parent == 0 && !bc_isret(bc_op(J->cur.startins))))) { | ||
668 | /* NYI: specialize to frame type and return directly, not via RET*. */ | ||
669 | for (i = -1; i < (ptrdiff_t)rbase; i++) | ||
670 | J->base[i] = 0; /* Purge dead slots. */ | ||
671 | J->maxslot = rbase + (BCReg)gotresults; | ||
672 | rec_stop(J, LJ_TRLINK_RETURN, 0); /* Return to interpreter. */ | ||
673 | return; | ||
674 | } | ||
664 | if (frame_isvarg(frame)) { | 675 | if (frame_isvarg(frame)) { |
665 | BCReg cbase = (BCReg)frame_delta(frame); | 676 | BCReg cbase = (BCReg)frame_delta(frame); |
666 | if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ | 677 | if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ |
@@ -1283,7 +1294,7 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val) | |||
1283 | /* -- Record calls to Lua functions --------------------------------------- */ | 1294 | /* -- Record calls to Lua functions --------------------------------------- */ |
1284 | 1295 | ||
1285 | /* Check unroll limits for calls. */ | 1296 | /* Check unroll limits for calls. */ |
1286 | static void check_call_unroll(jit_State *J) | 1297 | static void check_call_unroll(jit_State *J, TraceNo lnk) |
1287 | { | 1298 | { |
1288 | IRRef fref = tref_ref(J->base[-1]); | 1299 | IRRef fref = tref_ref(J->base[-1]); |
1289 | int32_t count = 0; | 1300 | int32_t count = 0; |
@@ -1300,8 +1311,14 @@ static void check_call_unroll(jit_State *J) | |||
1300 | rec_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ | 1311 | rec_stop(J, LJ_TRLINK_UPREC, J->cur.traceno); /* Up-recursion. */ |
1301 | } | 1312 | } |
1302 | } else { | 1313 | } else { |
1303 | if (count > J->param[JIT_P_callunroll]) | 1314 | if (count > J->param[JIT_P_callunroll]) { |
1315 | if (lnk) { /* Possible tail- or up-recursion. */ | ||
1316 | lj_trace_flush(J, lnk); /* Flush trace that only returns. */ | ||
1317 | /* Set a small, pseudo-random hotcount for a quick retry of JFUNC*. */ | ||
1318 | hotcount_set(J2GG(J), J->pc+1, LJ_PRNG_BITS(J, 4)); | ||
1319 | } | ||
1304 | lj_trace_err(J, LJ_TRERR_CUNROLL); | 1320 | lj_trace_err(J, LJ_TRERR_CUNROLL); |
1321 | } | ||
1305 | } | 1322 | } |
1306 | } | 1323 | } |
1307 | 1324 | ||
@@ -1346,13 +1363,23 @@ static void rec_func_vararg(jit_State *J) | |||
1346 | static void rec_func_lua(jit_State *J) | 1363 | static void rec_func_lua(jit_State *J) |
1347 | { | 1364 | { |
1348 | rec_func_setup(J); | 1365 | rec_func_setup(J); |
1349 | check_call_unroll(J); | 1366 | check_call_unroll(J, 0); |
1350 | } | 1367 | } |
1351 | 1368 | ||
1352 | /* Record entry to an already compiled function. */ | 1369 | /* Record entry to an already compiled function. */ |
1353 | static void rec_func_jit(jit_State *J, TraceNo lnk) | 1370 | static void rec_func_jit(jit_State *J, TraceNo lnk) |
1354 | { | 1371 | { |
1372 | GCtrace *T; | ||
1355 | rec_func_setup(J); | 1373 | rec_func_setup(J); |
1374 | T = traceref(J, lnk); | ||
1375 | if (T->linktype == LJ_TRLINK_RETURN) { /* Trace returns to interpreter? */ | ||
1376 | check_call_unroll(J, lnk); | ||
1377 | /* Temporarily unpatch JFUNC* to continue recording across function. */ | ||
1378 | J->patchins = *J->pc; | ||
1379 | J->patchpc = (BCIns *)J->pc; | ||
1380 | *J->patchpc = T->startins; | ||
1381 | return; | ||
1382 | } | ||
1356 | J->instunroll = 0; /* Cannot continue across a compiled function. */ | 1383 | J->instunroll = 0; /* Cannot continue across a compiled function. */ |
1357 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) | 1384 | if (J->pc == J->startpc && J->framedepth + J->retdepth == 0) |
1358 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-recursion. */ | 1385 | rec_stop(J, LJ_TRLINK_TAILREC, J->cur.traceno); /* Extra tail-recursion. */ |