aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-01-29 03:32:37 +0100
committerMike Pall <mike>2010-01-29 03:32:37 +0100
commit8681b7330f9ec97c46d1475ce16e0a2c202936e3 (patch)
tree1153011a6464f6f4a04518b33b4036bab28215e1 /src
parent272b2f7368464917919ddd1c7a876937144c16c8 (diff)
downloadluajit-8681b7330f9ec97c46d1475ce16e0a2c202936e3.tar.gz
luajit-8681b7330f9ec97c46d1475ce16e0a2c202936e3.tar.bz2
luajit-8681b7330f9ec97c46d1475ce16e0a2c202936e3.zip
Compile return to lower frame. Only for Lua frames right now.
Diffstat (limited to 'src')
-rw-r--r--src/lj_asm.c24
-rw-r--r--src/lj_ir.h2
-rw-r--r--src/lj_record.c89
3 files changed, 75 insertions, 40 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c
index 4f5610b0..c7527c15 100644
--- a/src/lj_asm.c
+++ b/src/lj_asm.c
@@ -1369,6 +1369,22 @@ static void asm_call(ASMState *as, IRIns *ir)
1369 asm_gencall(as, ci, args); 1369 asm_gencall(as, ci, args);
1370} 1370}
1371 1371
1372/* -- Returns ------------------------------------------------------------- */
1373
1374/* Return to lower frame. Guard that it goes to the right spot. */
1375static void asm_retf(ASMState *as, IRIns *ir)
1376{
1377 Reg base = ra_alloc1(as, REF_BASE, RSET_GPR);
1378 void *pc = ir_kptr(IR(ir->op2));
1379 int32_t delta = 1+bc_a(*((const BCIns *)pc - 1));
1380 as->topslot -= (BCReg)delta;
1381 if ((int32_t)as->topslot < 0) as->topslot = 0;
1382 emit_setgl(as, base, jit_base);
1383 emit_addptr(as, base, -8*delta);
1384 asm_guardcc(as, CC_NE);
1385 emit_gmroi(as, XG_ARITHi(XOg_CMP), base, -4, ptr2addr(pc));
1386}
1387
1372/* -- Type conversions ---------------------------------------------------- */ 1388/* -- Type conversions ---------------------------------------------------- */
1373 1389
1374static void asm_tonum(ASMState *as, IRIns *ir) 1390static void asm_tonum(ASMState *as, IRIns *ir)
@@ -2795,14 +2811,14 @@ static void asm_head_base(ASMState *as)
2795** Stack overflow is rare, so let the regular exit handling fix this up. 2811** Stack overflow is rare, so let the regular exit handling fix this up.
2796** This is done in the context of the *parent* trace and parent exitno! 2812** This is done in the context of the *parent* trace and parent exitno!
2797*/ 2813*/
2798static void asm_checkstack(ASMState *as, RegSet allow) 2814static void asm_checkstack(ASMState *as, BCReg topslot, RegSet allow)
2799{ 2815{
2800 /* Try to get an unused temp. register, otherwise spill/restore eax. */ 2816 /* Try to get an unused temp. register, otherwise spill/restore eax. */
2801 Reg r = allow ? rset_pickbot(allow) : RID_EAX; 2817 Reg r = allow ? rset_pickbot(allow) : RID_EAX;
2802 emit_jcc(as, CC_B, exitstub_addr(as->J, as->J->exitno)); 2818 emit_jcc(as, CC_B, exitstub_addr(as->J, as->J->exitno));
2803 if (allow == RSET_EMPTY) /* Restore temp. register. */ 2819 if (allow == RSET_EMPTY) /* Restore temp. register. */
2804 emit_rmro(as, XO_MOV, r, RID_ESP, sps_scale(SPS_TEMP1)); 2820 emit_rmro(as, XO_MOV, r, RID_ESP, sps_scale(SPS_TEMP1));
2805 emit_gri(as, XG_ARITHi(XOg_CMP), r, (int32_t)(8*as->topslot)); 2821 emit_gri(as, XG_ARITHi(XOg_CMP), r, (int32_t)(8*topslot));
2806 emit_rmro(as, XO_ARITH(XOg_SUB), r, RID_NONE, ptr2addr(&J2G(as->J)->jit_base)); 2822 emit_rmro(as, XO_ARITH(XOg_SUB), r, RID_NONE, ptr2addr(&J2G(as->J)->jit_base));
2807 emit_rmro(as, XO_MOV, r, r, offsetof(lua_State, maxstack)); 2823 emit_rmro(as, XO_MOV, r, r, offsetof(lua_State, maxstack));
2808 emit_getgl(as, r, jit_L); 2824 emit_getgl(as, r, jit_L);
@@ -2952,7 +2968,7 @@ static void asm_head_side(ASMState *as)
2952 2968
2953 /* Check Lua stack size if frames have been added. */ 2969 /* Check Lua stack size if frames have been added. */
2954 if (as->topslot) 2970 if (as->topslot)
2955 asm_checkstack(as, allow & RSET_GPR); 2971 asm_checkstack(as, as->topslot, allow & RSET_GPR);
2956} 2972}
2957 2973
2958/* -- Tail of trace ------------------------------------------------------- */ 2974/* -- Tail of trace ------------------------------------------------------- */
@@ -3110,6 +3126,8 @@ static void asm_ir(ASMState *as, IRIns *ir)
3110 case IR_EQ: asm_comp(as, ir, CC_NE, CC_NE, VCC_P); break; 3126 case IR_EQ: asm_comp(as, ir, CC_NE, CC_NE, VCC_P); break;
3111 case IR_NE: asm_comp(as, ir, CC_E, CC_E, VCC_U|VCC_P); break; 3127 case IR_NE: asm_comp(as, ir, CC_E, CC_E, VCC_U|VCC_P); break;
3112 3128
3129 case IR_RETF: asm_retf(as, ir); break;
3130
3113 /* Bit ops. */ 3131 /* Bit ops. */
3114 case IR_BNOT: asm_bitnot(as, ir); break; 3132 case IR_BNOT: asm_bitnot(as, ir); break;
3115 case IR_BSWAP: asm_bitswap(as, ir); break; 3133 case IR_BSWAP: asm_bitswap(as, ir); break;
diff --git a/src/lj_ir.h b/src/lj_ir.h
index 34c14519..e110607d 100644
--- a/src/lj_ir.h
+++ b/src/lj_ir.h
@@ -34,7 +34,7 @@
34 _(NE, GC, ref, ref) \ 34 _(NE, GC, ref, ref) \
35 \ 35 \
36 _(ABC, G , ref, ref) \ 36 _(ABC, G , ref, ref) \
37 _(UNUSED, G , ref, ref) /* Placeholder. */ \ 37 _(RETF, G , ref, ref) \
38 \ 38 \
39 _(LT, G , ref, ref) \ 39 _(LT, G , ref, ref) \
40 _(GE, G , ref, ref) \ 40 _(GE, G , ref, ref) \
diff --git a/src/lj_record.c b/src/lj_record.c
index a82bb643..03fcb966 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -64,7 +64,7 @@ enum {
64 64
65/* Forward declarations. */ 65/* Forward declarations. */
66static TRef rec_idx(jit_State *J, RecordIndex *ix); 66static TRef rec_idx(jit_State *J, RecordIndex *ix);
67static int rec_call(jit_State *J, BCReg func, int cres, int nargs); 67static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs);
68 68
69/* -- Sanity checks ------------------------------------------------------- */ 69/* -- Sanity checks ------------------------------------------------------- */
70 70
@@ -848,9 +848,9 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
848typedef struct RecordFFData { 848typedef struct RecordFFData {
849 TValue *argv; /* Runtime argument values. */ 849 TValue *argv; /* Runtime argument values. */
850 GCfunc *fn; /* The currently recorded function. */ 850 GCfunc *fn; /* The currently recorded function. */
851 int nargs; /* Number of passed arguments. */ 851 ptrdiff_t nargs; /* Number of passed arguments. */
852 int nres; /* Number of returned results (defaults to 1). */ 852 ptrdiff_t nres; /* Number of returned results (defaults to 1). */
853 int cres; /* Wanted number of call results. */ 853 ptrdiff_t cres; /* Wanted number of call results. */
854 uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */ 854 uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */
855} RecordFFData; 855} RecordFFData;
856 856
@@ -909,10 +909,10 @@ static void recff_c(jit_State *J, TRef *res, RecordFFData *rd)
909static void recff_assert(jit_State *J, TRef *res, RecordFFData *rd) 909static void recff_assert(jit_State *J, TRef *res, RecordFFData *rd)
910{ 910{
911 /* Arguments already specialized. The interpreter throws for nil/false. */ 911 /* Arguments already specialized. The interpreter throws for nil/false. */
912 BCReg i; 912 ptrdiff_t i;
913 for (i = 0; arg[i]; i++) /* Need to pass through all arguments. */ 913 for (i = 0; arg[i]; i++) /* Need to pass through all arguments. */
914 res[i] = arg[i]; 914 res[i] = arg[i];
915 rd->nres = (int)i; 915 rd->nres = i;
916 UNUSED(J); 916 UNUSED(J);
917} 917}
918 918
@@ -1067,7 +1067,7 @@ static void recff_pcall(jit_State *J, TRef *res, RecordFFData *rd)
1067 BCReg parg = (BCReg)(arg - J->base); 1067 BCReg parg = (BCReg)(arg - J->base);
1068 if (rec_call(J, parg, CALLRES_MULTI, rd->nargs - 1)) { /* Resolved call. */ 1068 if (rec_call(J, parg, CALLRES_MULTI, rd->nargs - 1)) { /* Resolved call. */
1069 res[0] = TREF_TRUE; /* Prepend true result. No need to move results. */ 1069 res[0] = TREF_TRUE; /* Prepend true result. No need to move results. */
1070 rd->nres = (int)((J->maxslot - parg) + 1); 1070 rd->nres = (ptrdiff_t)J->maxslot - (ptrdiff_t)parg + 1;
1071 } else { /* Propagate pending call. */ 1071 } else { /* Propagate pending call. */
1072 rd->cres = CALLRES_PENDING; 1072 rd->cres = CALLRES_PENDING;
1073 } 1073 }
@@ -1076,8 +1076,8 @@ static void recff_pcall(jit_State *J, TRef *res, RecordFFData *rd)
1076 1076
1077/* Struct to pass context across lj_vm_cpcall. */ 1077/* Struct to pass context across lj_vm_cpcall. */
1078typedef struct RecordXpcall { 1078typedef struct RecordXpcall {
1079 ptrdiff_t nargs;
1079 BCReg parg; 1080 BCReg parg;
1080 int nargs;
1081 int resolved; 1081 int resolved;
1082} RecordXpcall; 1082} RecordXpcall;
1083 1083
@@ -1117,7 +1117,7 @@ static void recff_xpcall(jit_State *J, TRef *res, RecordFFData *rd)
1117 if (errcode) 1117 if (errcode)
1118 lj_err_throw(J->L, errcode); /* Propagate errors. */ 1118 lj_err_throw(J->L, errcode); /* Propagate errors. */
1119 if (rx.resolved) { /* Resolved call. */ 1119 if (rx.resolved) { /* Resolved call. */
1120 int i, nres = (int)(J->maxslot - parg); 1120 ptrdiff_t i, nres = (ptrdiff_t)J->maxslot - (ptrdiff_t)parg;
1121 rd->nres = nres + 1; 1121 rd->nres = nres + 1;
1122 res[0] = TREF_TRUE; /* Prepend true result. */ 1122 res[0] = TREF_TRUE; /* Prepend true result. */
1123 for (i = 1; i <= nres; i++) /* Move results down. */ 1123 for (i = 1; i <= nres; i++) /* Move results down. */
@@ -1354,7 +1354,7 @@ static void recff_string_range(jit_State *J, TRef *res, RecordFFData *rd)
1354 res[0] = lj_ir_kstr(J, lj_str_new(J->L, strdata(str), 0)); 1354 res[0] = lj_ir_kstr(J, lj_str_new(J->L, strdata(str), 0));
1355 } 1355 }
1356 } else { /* Return string.byte result(s). */ 1356 } else { /* Return string.byte result(s). */
1357 int32_t i, len = end - start; 1357 ptrdiff_t i, len = end - start;
1358 if (len > 0) { 1358 if (len > 0) {
1359 TRef trslen = emitir(IRTI(IR_SUB), trend, trstart); 1359 TRef trslen = emitir(IRTI(IR_SUB), trend, trstart);
1360 emitir(IRTGI(IR_EQ), trslen, lj_ir_kint(J, len)); 1360 emitir(IRTGI(IR_EQ), trslen, lj_ir_kint(J, len));
@@ -1498,46 +1498,63 @@ static void recff_io_flush(jit_State *J, TRef *res, RecordFFData *rd)
1498#include "lj_recdef.h" 1498#include "lj_recdef.h"
1499 1499
1500/* Record return. */ 1500/* Record return. */
1501static void rec_ret(jit_State *J, BCReg rbase, int gotresults) 1501static void rec_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
1502{ 1502{
1503 TValue *frame = J->L->base - 1; 1503 TValue *frame = J->L->base - 1;
1504 TRef *res = J->base + rbase; 1504 ptrdiff_t i;
1505 for (i = 0; i < gotresults; i++)
1506 getslot(J, rbase+i); /* Ensure all results have a reference. */
1505 J->tailcalled = 0; 1507 J->tailcalled = 0;
1506 while (frame_ispcall(frame)) { 1508 while (frame_ispcall(frame)) { /* Immediately resolve pcall() returns. */
1507 BCReg cbase = (BCReg)frame_delta(frame); 1509 BCReg cbase = (BCReg)frame_delta(frame);
1508 if (J->framedepth-- <= 0) 1510 if (J->framedepth-- <= 0)
1509 lj_trace_err(J, LJ_TRERR_NYIRETL); 1511 lj_trace_err(J, LJ_TRERR_NYIRETL);
1510 lua_assert(J->baseslot > 1); 1512 lua_assert(J->baseslot > 1);
1513 J->base[--rbase] = TREF_TRUE; /* Prepend true to results. */
1514 gotresults++;
1515 rbase += cbase;
1511 J->baseslot -= (BCReg)cbase; 1516 J->baseslot -= (BCReg)cbase;
1512 J->base -= cbase; 1517 J->base -= cbase;
1513 *--res = TREF_TRUE; /* Prepend true to results. */
1514 gotresults++;
1515 frame = frame_prevd(frame); 1518 frame = frame_prevd(frame);
1516 } 1519 }
1517 if (J->framedepth-- <= 0) 1520 if (frame_islua(frame)) { /* Return to Lua frame. */
1518 lj_trace_err(J, LJ_TRERR_NYIRETL); 1521 BCIns callins = *(frame_pc(frame)-1);
1519 lua_assert(J->baseslot > 1); 1522 ptrdiff_t nresults = bc_b(callins) ? (ptrdiff_t)bc_b(callins)-1 :gotresults;
1520 if (frame_islua(frame)) {
1521 BCIns callins = *(J->pc = frame_pc(frame)-1);
1522 ptrdiff_t nresults = bc_b(callins) ? (int)bc_b(callins)-1 : gotresults;
1523 BCReg cbase = bc_a(callins); 1523 BCReg cbase = bc_a(callins);
1524 int i; 1524 for (i = 0; i < nresults; i++) /* Adjust results. */
1525 for (i = 0; i < nresults; i++) 1525 J->base[i-1] = i < gotresults ? J->base[rbase+i] : TREF_NIL;
1526 J->base[i-1] = i < gotresults ? res[i] : TREF_NIL;
1527 J->maxslot = cbase+(BCReg)nresults; 1526 J->maxslot = cbase+(BCReg)nresults;
1528 J->baseslot -= cbase+1; 1527 if (J->framedepth > 0) { /* Return to a frame that is part of the trace. */
1529 J->base -= cbase+1; 1528 J->framedepth--;
1530 } else if (frame_iscont(frame)) { 1529 lua_assert(J->baseslot > cbase+1);
1530 J->baseslot -= cbase+1;
1531 J->base -= cbase+1;
1532 } else if (J->parent == 0) {
1533 /* Return to lower frame would leave the loop in a root trace. */
1534 lj_trace_err(J, LJ_TRERR_LLEAVE);
1535 } else { /* Return to lower frame. Guard for the target we return to. */
1536 GCproto *pt = funcproto(frame_func(frame - (cbase+1)));
1537 TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO);
1538 TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame));
1539 emitir(IRTG(IR_RETF, IRT_PTR), trpt, trpc);
1540 J->needsnap = 1;
1541 lua_assert(J->baseslot == 1);
1542 /* Shift result slots up and clear the slots of the new frame below. */
1543 memmove(J->base + cbase, J->base-1, sizeof(TRef)*nresults);
1544 memset(J->base-1, 0, sizeof(TRef)*(cbase+1));
1545 }
1546 } else if (frame_iscont(frame)) { /* Return to continuation frame. */
1531 ASMFunction cont = frame_contf(frame); 1547 ASMFunction cont = frame_contf(frame);
1532 BCReg cbase = (BCReg)frame_delta(frame); 1548 BCReg cbase = (BCReg)frame_delta(frame);
1533 J->pc = frame_contpc(frame)-1; 1549 if (J->framedepth-- <= 0)
1550 lj_trace_err(J, LJ_TRERR_NYIRETL);
1534 J->baseslot -= (BCReg)cbase; 1551 J->baseslot -= (BCReg)cbase;
1535 J->base -= cbase; 1552 J->base -= cbase;
1536 J->maxslot = cbase-2; 1553 J->maxslot = cbase-2;
1537 if (cont == lj_cont_ra) { 1554 if (cont == lj_cont_ra) {
1538 /* Copy result to destination slot. */ 1555 /* Copy result to destination slot. */
1539 BCReg dst = bc_a(*J->pc); 1556 BCReg dst = bc_a(*(frame_contpc(frame)-1));
1540 J->base[dst] = gotresults ? res[0] : TREF_NIL; 1557 J->base[dst] = gotresults ? J->base[cbase+rbase] : TREF_NIL;
1541 if (dst > J->maxslot) J->maxslot = dst+1; 1558 if (dst > J->maxslot) J->maxslot = dst+1;
1542 } else if (cont == lj_cont_nop) { 1559 } else if (cont == lj_cont_nop) {
1543 /* Nothing to do here. */ 1560 /* Nothing to do here. */
@@ -1548,7 +1565,7 @@ static void rec_ret(jit_State *J, BCReg rbase, int gotresults)
1548 lua_assert(cont == lj_cont_condf || cont == lj_cont_condt); 1565 lua_assert(cont == lj_cont_condf || cont == lj_cont_condt);
1549 } 1566 }
1550 } else { 1567 } else {
1551 lua_assert(0); 1568 lj_trace_err(J, LJ_TRERR_NYIRETL); /* NYI: handle return to C frame. */
1552 } 1569 }
1553 lua_assert(J->baseslot >= 1); 1570 lua_assert(J->baseslot >= 1);
1554} 1571}
@@ -1576,7 +1593,7 @@ static void check_call_unroll(jit_State *J, GCfunc *fn)
1576} 1593}
1577 1594
1578/* Record call. Returns 0 for pending calls and 1 for resolved calls. */ 1595/* Record call. Returns 0 for pending calls and 1 for resolved calls. */
1579static int rec_call(jit_State *J, BCReg func, int cres, int nargs) 1596static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs)
1580{ 1597{
1581 RecordFFData rd; 1598 RecordFFData rd;
1582 TRef trfunc, *res = &J->base[func]; 1599 TRef trfunc, *res = &J->base[func];
@@ -1587,7 +1604,7 @@ static int rec_call(jit_State *J, BCReg func, int cres, int nargs)
1587 rd.argv = tv+1; 1604 rd.argv = tv+1;
1588 } else { /* Otherwise resolve __call metamethod for called object. */ 1605 } else { /* Otherwise resolve __call metamethod for called object. */
1589 RecordIndex ix; 1606 RecordIndex ix;
1590 int i; 1607 ptrdiff_t i;
1591 ix.tab = res[0]; 1608 ix.tab = res[0];
1592 copyTV(J->L, &ix.tabv, tv); 1609 copyTV(J->L, &ix.tabv, tv);
1593 if (!rec_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj)) 1610 if (!rec_mm_lookup(J, &ix, MM_call) || !tref_isfunc(ix.mobj))
@@ -1619,7 +1636,7 @@ static int rec_call(jit_State *J, BCReg func, int cres, int nargs)
1619 } 1636 }
1620 check_call_unroll(J, rd.fn); 1637 check_call_unroll(J, rd.fn);
1621 if (cres == CALLRES_TAILCALL) { 1638 if (cres == CALLRES_TAILCALL) {
1622 int i; 1639 ptrdiff_t i;
1623 /* 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. */
1624 if (++J->tailcalled > J->loopunroll) 1641 if (++J->tailcalled > J->loopunroll)
1625 lj_trace_err(J, LJ_TRERR_LUNROLL); 1642 lj_trace_err(J, LJ_TRERR_LUNROLL);
@@ -1982,7 +1999,7 @@ void lj_record_ins(jit_State *J)
1982 /* fallthrough */ 1999 /* fallthrough */
1983 case BC_CALL: 2000 case BC_CALL:
1984 callop: 2001 callop:
1985 rec_call(J, ra, (int)(rb-1), (int)(rc-1)); 2002 rec_call(J, ra, (ptrdiff_t)rb-1, (ptrdiff_t)rc-1);
1986 break; 2003 break;
1987 2004
1988 /* -- Returns ----------------------------------------------------------- */ 2005 /* -- Returns ----------------------------------------------------------- */
@@ -1992,7 +2009,7 @@ void lj_record_ins(jit_State *J)
1992 rc = (BCReg)(J->L->top - J->L->base) - ra + 1; 2009 rc = (BCReg)(J->L->top - J->L->base) - ra + 1;
1993 /* fallthrough */ 2010 /* fallthrough */
1994 case BC_RET: case BC_RET0: case BC_RET1: 2011 case BC_RET: case BC_RET0: case BC_RET1:
1995 rec_ret(J, ra, (int)(rc-1)); 2012 rec_ret(J, ra, (ptrdiff_t)rc-1);
1996 break; 2013 break;
1997 2014
1998 /* -- Loops and branches ------------------------------------------------ */ 2015 /* -- Loops and branches ------------------------------------------------ */