aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-02-03 16:48:25 +0100
committerMike Pall <mike>2010-02-03 16:48:25 +0100
commit78f5e2ffd34e01626b910341a7808ea4be8a6d0d (patch)
tree5807c66c9cff3209095407ff7424be26ddd461c3 /src
parent318e86c7eb53999783c0c4a3c6796d1a723dd024 (diff)
downloadluajit-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.c24
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. */
1577static void check_call_unroll(jit_State *J, GCfunc *fn) 1577static 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() */