diff options
author | Mike Pall <mike> | 2010-02-03 16:48:25 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2010-02-03 16:48:25 +0100 |
commit | 78f5e2ffd34e01626b910341a7808ea4be8a6d0d (patch) | |
tree | 5807c66c9cff3209095407ff7424be26ddd461c3 /src | |
parent | 318e86c7eb53999783c0c4a3c6796d1a723dd024 (diff) | |
download | luajit-78f5e2ffd34e01626b910341a7808ea4be8a6d0d.tar.gz luajit-78f5e2ffd34e01626b910341a7808ea4be8a6d0d.tar.bz2 luajit-78f5e2ffd34e01626b910341a7808ea4be8a6d0d.zip |
Fix unroll limit checks and frame depth adjustment for pcall.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_record.c | 24 |
1 files changed, 11 insertions, 13 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 682246d7..824d2fd1 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -1576,22 +1576,18 @@ static void rec_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) | |||
1576 | /* Check unroll limits for calls. */ | 1576 | /* Check unroll limits for calls. */ |
1577 | static void check_call_unroll(jit_State *J, GCfunc *fn) | 1577 | static void check_call_unroll(jit_State *J, GCfunc *fn) |
1578 | { | 1578 | { |
1579 | TValue *first = J->L->base - J->baseslot; | 1579 | IRRef fref = tref_ref(J->base[-1]); |
1580 | TValue *frame = J->L->base - 1; | 1580 | int32_t count = 0; |
1581 | int count = 0; | 1581 | ptrdiff_t s; |
1582 | while (frame > first) { | 1582 | for (s = (ptrdiff_t)J->baseslot - 1; s > 0; s--) |
1583 | if (frame_func(frame) == fn) | 1583 | if ((J->slot[s] & TREF_FRAME) && tref_ref(J->slot[s]) == fref) |
1584 | count++; | 1584 | count++; |
1585 | if (frame_isvarg(frame)) | ||
1586 | frame = frame_prevd(frame); | ||
1587 | frame = frame_prev(frame); | ||
1588 | } | ||
1589 | if (bc_op(J->cur.startins) == BC_CALL && | 1585 | if (bc_op(J->cur.startins) == BC_CALL && |
1590 | funcproto(fn) == &gcref(J->cur.startpt)->pt) { | 1586 | funcproto(fn) == &gcref(J->cur.startpt)->pt) { |
1591 | if (count + J->tailcalled >= J->param[JIT_P_recunroll]) | 1587 | if (count + J->tailcalled > J->param[JIT_P_recunroll]) |
1592 | lj_trace_err(J, LJ_TRERR_NYIRECU); | 1588 | lj_trace_err(J, LJ_TRERR_NYIRECU); |
1593 | } else { | 1589 | } else { |
1594 | if (count >= J->param[JIT_P_callunroll]) | 1590 | if (count > J->param[JIT_P_callunroll]) |
1595 | lj_trace_err(J, LJ_TRERR_CUNROLL); | 1591 | lj_trace_err(J, LJ_TRERR_CUNROLL); |
1596 | } | 1592 | } |
1597 | } | 1593 | } |
@@ -1625,6 +1621,7 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs) | |||
1625 | trfunc = lj_ir_kfunc(J, rd.fn); | 1621 | trfunc = lj_ir_kfunc(J, rd.fn); |
1626 | emitir(IRTG(IR_EQ, IRT_FUNC), res[0], trfunc); | 1622 | emitir(IRTG(IR_EQ, IRT_FUNC), res[0], trfunc); |
1627 | res[0] = trfunc | TREF_FRAME; | 1623 | res[0] = trfunc | TREF_FRAME; |
1624 | J->framedepth++; | ||
1628 | 1625 | ||
1629 | if (isluafunc(rd.fn)) { /* Record call to Lua function. */ | 1626 | if (isluafunc(rd.fn)) { /* Record call to Lua function. */ |
1630 | GCproto *pt = funcproto(rd.fn); | 1627 | GCproto *pt = funcproto(rd.fn); |
@@ -1638,7 +1635,6 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs) | |||
1638 | if (rd.fn->l.gate != lj_gate_lf) | 1635 | if (rd.fn->l.gate != lj_gate_lf) |
1639 | lj_trace_err(J, LJ_TRERR_NYILNKF); | 1636 | lj_trace_err(J, LJ_TRERR_NYILNKF); |
1640 | } | 1637 | } |
1641 | check_call_unroll(J, rd.fn); | ||
1642 | if (cres == CALLRES_TAILCALL) { | 1638 | if (cres == CALLRES_TAILCALL) { |
1643 | ptrdiff_t i; | 1639 | ptrdiff_t i; |
1644 | /* Tailcalls can form a loop, so count towards the loop unroll limit. */ | 1640 | /* Tailcalls can form a loop, so count towards the loop unroll limit. */ |
@@ -1646,11 +1642,11 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs) | |||
1646 | lj_trace_err(J, LJ_TRERR_LUNROLL); | 1642 | lj_trace_err(J, LJ_TRERR_LUNROLL); |
1647 | for (i = 0; i <= nargs; i++) /* Move func + args down. */ | 1643 | for (i = 0; i <= nargs; i++) /* Move func + args down. */ |
1648 | J->base[i-1] = res[i]; | 1644 | J->base[i-1] = res[i]; |
1645 | J->framedepth--; | ||
1649 | /* Note: the new FRAME is now at J->base[-1] (even for slot #0). */ | 1646 | /* Note: the new FRAME is now at J->base[-1] (even for slot #0). */ |
1650 | } else { /* Regular call. */ | 1647 | } else { /* Regular call. */ |
1651 | J->base += func+1; | 1648 | J->base += func+1; |
1652 | J->baseslot += func+1; | 1649 | J->baseslot += func+1; |
1653 | J->framedepth++; | ||
1654 | } | 1650 | } |
1655 | if (J->baseslot + pt->framesize >= LJ_MAX_JSLOTS) | 1651 | if (J->baseslot + pt->framesize >= LJ_MAX_JSLOTS) |
1656 | lj_trace_err(J, LJ_TRERR_STACKOV); | 1652 | lj_trace_err(J, LJ_TRERR_STACKOV); |
@@ -1659,6 +1655,7 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs) | |||
1659 | J->base[nargs++] = TREF_NIL; | 1655 | J->base[nargs++] = TREF_NIL; |
1660 | /* The remaining slots should never be read before they are written. */ | 1656 | /* The remaining slots should never be read before they are written. */ |
1661 | J->maxslot = pt->numparams; | 1657 | J->maxslot = pt->numparams; |
1658 | check_call_unroll(J, rd.fn); | ||
1662 | return 0; /* No result yet. */ | 1659 | return 0; /* No result yet. */ |
1663 | } else { /* Record call to C function or fast function. */ | 1660 | } else { /* Record call to C function or fast function. */ |
1664 | uint32_t m = 0; | 1661 | uint32_t m = 0; |
@@ -1670,6 +1667,7 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs) | |||
1670 | rd.cres = cres; | 1667 | rd.cres = cres; |
1671 | rd.nres = 1; /* Default is one result. */ | 1668 | rd.nres = 1; /* Default is one result. */ |
1672 | (recff_func[m >> 8])(J, res, &rd); /* Call recff_* handler. */ | 1669 | (recff_func[m >> 8])(J, res, &rd); /* Call recff_* handler. */ |
1670 | J->framedepth--; | ||
1673 | cres = rd.cres; | 1671 | cres = rd.cres; |
1674 | if (cres >= 0) { | 1672 | if (cres >= 0) { |
1675 | /* Caller takes fixed number of results: local a,b = f() */ | 1673 | /* Caller takes fixed number of results: local a,b = f() */ |