diff options
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. */ |
