summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
authorMike Pall <mike>2010-02-04 03:08:29 +0100
committerMike Pall <mike>2010-02-04 03:08:29 +0100
commit7256690364a2c9a5e9269ffd89bc132ee188480d (patch)
tree20d8a6a37fb64492e12407ee412b4c2f10137e93 /src/lj_record.c
parent78f5e2ffd34e01626b910341a7808ea4be8a6d0d (diff)
downloadluajit-7256690364a2c9a5e9269ffd89bc132ee188480d.tar.gz
luajit-7256690364a2c9a5e9269ffd89bc132ee188480d.tar.bz2
luajit-7256690364a2c9a5e9269ffd89bc132ee188480d.zip
Add shadow frame link stack for trace recorder.
Simplifies snapshots. Prerequisite for pre-call snapshots. Increases consistency for fast function calls, too.
Diffstat (limited to 'src/lj_record.c')
-rw-r--r--src/lj_record.c63
1 files changed, 55 insertions, 8 deletions
diff --git a/src/lj_record.c b/src/lj_record.c
index 824d2fd1..f6d13264 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -101,20 +101,45 @@ static void rec_check_ir(jit_State *J)
101 } 101 }
102} 102}
103 103
104/* Compare frame stack of the recorder and the VM. */
105static void rec_check_frames(jit_State *J)
106{
107 cTValue *frame = J->L->base - 1;
108 cTValue *lim = J->L->base - J->baseslot;
109 int32_t depth = J->framedepth;
110 while (frame > lim) {
111 depth--;
112 lua_assert(depth >= 0);
113 lua_assert((SnapEntry)frame_ftsz(frame) == J->frame[depth]);
114 if (frame_iscont(frame)) {
115 depth--;
116 lua_assert(depth >= 0);
117 lua_assert((SnapEntry)frame_ftsz(frame-1) == J->frame[depth]);
118 }
119 frame = frame_prev(frame);
120 }
121 lua_assert(depth == 0);
122}
123
104/* Sanity check the slots. */ 124/* Sanity check the slots. */
105static void rec_check_slots(jit_State *J) 125static void rec_check_slots(jit_State *J)
106{ 126{
107 BCReg s, nslots = J->baseslot + J->maxslot; 127 BCReg s, nslots = J->baseslot + J->maxslot;
128 int32_t depth;
108 lua_assert(J->baseslot >= 1 && J->baseslot < LJ_MAX_JSLOTS); 129 lua_assert(J->baseslot >= 1 && J->baseslot < LJ_MAX_JSLOTS);
109 lua_assert(nslots < LJ_MAX_JSLOTS); 130 lua_assert(nslots < LJ_MAX_JSLOTS);
110 for (s = 0; s < nslots; s++) { 131 for (s = 0; s < nslots; s++) {
111 TRef tr = J->slot[s]; 132 TRef tr = J->slot[s];
133 if (s != 0 && (tr & (TREF_CONT|TREF_FRAME)))
134 depth++;
112 if (tr) { 135 if (tr) {
113 IRRef ref = tref_ref(tr); 136 IRRef ref = tref_ref(tr);
114 lua_assert(ref >= J->cur.nk && ref < J->cur.nins); 137 lua_assert(ref >= J->cur.nk && ref < J->cur.nins);
115 lua_assert(irt_t(IR(ref)->t) == tref_t(tr)); 138 lua_assert(irt_t(IR(ref)->t) == tref_t(tr));
116 } 139 }
117 } 140 }
141 lua_assert(J->framedepth == depth);
142 rec_check_frames(J);
118} 143}
119#endif 144#endif
120 145
@@ -854,6 +879,7 @@ typedef struct RecordFFData {
854 ptrdiff_t nres; /* Number of returned results (defaults to 1). */ 879 ptrdiff_t nres; /* Number of returned results (defaults to 1). */
855 ptrdiff_t cres; /* Wanted number of call results. */ 880 ptrdiff_t cres; /* Wanted number of call results. */
856 uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */ 881 uint32_t data; /* Per-ffid auxiliary data (opcode, literal etc.). */
882 int metacall; /* True if function was resolved via __call. */
857} RecordFFData; 883} RecordFFData;
858 884
859/* Type of handler to record a fast function. */ 885/* Type of handler to record a fast function. */
@@ -1020,9 +1046,14 @@ static void recff_tostring(jit_State *J, TRef *res, RecordFFData *rd)
1020 ix.tab = tr; 1046 ix.tab = tr;
1021 copyTV(J->L, &ix.tabv, &rd->argv[0]); 1047 copyTV(J->L, &ix.tabv, &rd->argv[0]);
1022 if (rec_mm_lookup(J, &ix, MM_tostring)) { /* Has __tostring metamethod? */ 1048 if (rec_mm_lookup(J, &ix, MM_tostring)) { /* Has __tostring metamethod? */
1049 if (rd->metacall) /* Must not use kludge. */
1050 recff_err_nyi(J, rd);
1023 res[0] = ix.mobj; 1051 res[0] = ix.mobj;
1024 copyTV(J->L, rd->argv - 1, &ix.mobjv); 1052 copyTV(J->L, rd->argv - 1, &ix.mobjv); /* Kludge. */
1025 if (!rec_call(J, (BCReg)(res - J->base), 1, 1)) /* Pending call? */ 1053 J->framedepth--;
1054 if (rec_call(J, (BCReg)(res - J->base), 1, 1))
1055 J->framedepth++;
1056 else
1026 rd->cres = CALLRES_PENDING; 1057 rd->cres = CALLRES_PENDING;
1027 /* Otherwise res[0] already contains the result. */ 1058 /* Otherwise res[0] already contains the result. */
1028 } else if (tref_isnumber(tr)) { 1059 } else if (tref_isnumber(tr)) {
@@ -1067,6 +1098,8 @@ static void recff_pcall(jit_State *J, TRef *res, RecordFFData *rd)
1067{ 1098{
1068 if (rd->nargs >= 1) { 1099 if (rd->nargs >= 1) {
1069 BCReg parg = (BCReg)(arg - J->base); 1100 BCReg parg = (BCReg)(arg - J->base);
1101 J->pc = (const BCIns *)(sizeof(TValue) - 4 +
1102 (hook_active(J2G(J)) ? FRAME_PCALLH : FRAME_PCALL));
1070 if (rec_call(J, parg, CALLRES_MULTI, rd->nargs - 1)) { /* Resolved call. */ 1103 if (rec_call(J, parg, CALLRES_MULTI, rd->nargs - 1)) { /* Resolved call. */
1071 res[0] = TREF_TRUE; /* Prepend true result. No need to move results. */ 1104 res[0] = TREF_TRUE; /* Prepend true result. No need to move results. */
1072 rd->nres = (ptrdiff_t)J->maxslot - (ptrdiff_t)parg + 1; 1105 rd->nres = (ptrdiff_t)J->maxslot - (ptrdiff_t)parg + 1;
@@ -1108,6 +1141,8 @@ static void recff_xpcall(jit_State *J, TRef *res, RecordFFData *rd)
1108 copyTV(J->L, &rd->argv[0], &argv1); 1141 copyTV(J->L, &rd->argv[0], &argv1);
1109 copyTV(J->L, &rd->argv[1], &argv0); 1142 copyTV(J->L, &rd->argv[1], &argv0);
1110 oargv = savestack(J->L, rd->argv); 1143 oargv = savestack(J->L, rd->argv);
1144 J->pc = (const BCIns *)(2*sizeof(TValue) - 4 +
1145 (hook_active(J2G(J)) ? FRAME_PCALLH : FRAME_PCALL));
1111 /* Need to protect rec_call because the recorder may throw. */ 1146 /* Need to protect rec_call because the recorder may throw. */
1112 rx.parg = parg; 1147 rx.parg = parg;
1113 rx.nargs = rd->nargs - 2; 1148 rx.nargs = rd->nargs - 2;
@@ -1549,7 +1584,7 @@ static void rec_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults)
1549 } else if (frame_iscont(frame)) { /* Return to continuation frame. */ 1584 } else if (frame_iscont(frame)) { /* Return to continuation frame. */
1550 ASMFunction cont = frame_contf(frame); 1585 ASMFunction cont = frame_contf(frame);
1551 BCReg cbase = (BCReg)frame_delta(frame); 1586 BCReg cbase = (BCReg)frame_delta(frame);
1552 if (J->framedepth-- <= 0) 1587 if ((J->framedepth -= 2) <= 0)
1553 lj_trace_err(J, LJ_TRERR_NYIRETL); 1588 lj_trace_err(J, LJ_TRERR_NYIRETL);
1554 J->baseslot -= (BCReg)cbase; 1589 J->baseslot -= (BCReg)cbase;
1555 J->base -= cbase; 1590 J->base -= cbase;
@@ -1602,6 +1637,7 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs)
1602 if (tref_isfunc(res[0])) { /* Regular function call. */ 1637 if (tref_isfunc(res[0])) { /* Regular function call. */
1603 rd.fn = funcV(tv); 1638 rd.fn = funcV(tv);
1604 rd.argv = tv+1; 1639 rd.argv = tv+1;
1640 rd.metacall = 0;
1605 } else { /* Otherwise resolve __call metamethod for called object. */ 1641 } else { /* Otherwise resolve __call metamethod for called object. */
1606 RecordIndex ix; 1642 RecordIndex ix;
1607 ptrdiff_t i; 1643 ptrdiff_t i;
@@ -1615,13 +1651,21 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs)
1615 res[0] = ix.mobj; 1651 res[0] = ix.mobj;
1616 rd.fn = funcV(&ix.mobjv); 1652 rd.fn = funcV(&ix.mobjv);
1617 rd.argv = tv; /* The called object is the 1st arg. */ 1653 rd.argv = tv; /* The called object is the 1st arg. */
1654 rd.metacall = 1;
1618 } 1655 }
1619 1656
1620 /* Specialize to the runtime value of the called function. */ 1657 /* Specialize to the runtime value of the called function. */
1621 trfunc = lj_ir_kfunc(J, rd.fn); 1658 trfunc = lj_ir_kfunc(J, rd.fn);
1622 emitir(IRTG(IR_EQ, IRT_FUNC), res[0], trfunc); 1659 emitir(IRTG(IR_EQ, IRT_FUNC), res[0], trfunc);
1623 res[0] = trfunc | TREF_FRAME; 1660 res[0] = trfunc | TREF_FRAME;
1624 J->framedepth++; 1661
1662 /* Add frame links. */
1663 J->frame[J->framedepth++] = SNAP_MKPC(J->pc+1);
1664 if (cres == CALLRES_CONT) /* Continuations need an extra frame stack slot. */
1665 J->frame[J->framedepth++] = SNAP_MKFTSZ((func+1)*sizeof(TValue)+FRAME_CONT);
1666 /* NYI: func is wrong if any fast function ever sets up a continuation. */
1667 if (J->framedepth > LJ_MAX_JFRAME)
1668 lj_trace_err(J, LJ_TRERR_STACKOV);
1625 1669
1626 if (isluafunc(rd.fn)) { /* Record call to Lua function. */ 1670 if (isluafunc(rd.fn)) { /* Record call to Lua function. */
1627 GCproto *pt = funcproto(rd.fn); 1671 GCproto *pt = funcproto(rd.fn);
@@ -1659,6 +1703,7 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs)
1659 return 0; /* No result yet. */ 1703 return 0; /* No result yet. */
1660 } else { /* Record call to C function or fast function. */ 1704 } else { /* Record call to C function or fast function. */
1661 uint32_t m = 0; 1705 uint32_t m = 0;
1706 BCReg oldmaxslot = J->maxslot;
1662 res[1+nargs] = 0; 1707 res[1+nargs] = 0;
1663 rd.nargs = nargs; 1708 rd.nargs = nargs;
1664 if (rd.fn->c.ffid < sizeof(recff_idmap)/sizeof(recff_idmap[0])) 1709 if (rd.fn->c.ffid < sizeof(recff_idmap)/sizeof(recff_idmap[0]))
@@ -1682,10 +1727,12 @@ static int rec_call(jit_State *J, BCReg func, ptrdiff_t cres, ptrdiff_t nargs)
1682 rec_ret(J, func, rd.nres); 1727 rec_ret(J, func, rd.nres);
1683 } else if (cres == CALLRES_CONT) { 1728 } else if (cres == CALLRES_CONT) {
1684 /* Note: immediately resolved continuations must not change J->maxslot. */ 1729 /* Note: immediately resolved continuations must not change J->maxslot. */
1730 J->maxslot = oldmaxslot;
1731 J->framedepth--;
1685 res[rd.nres] = TREF_NIL; /* Turn 0 results into nil result. */ 1732 res[rd.nres] = TREF_NIL; /* Turn 0 results into nil result. */
1686 } else { 1733 } else {
1687 J->framedepth++;
1688 lua_assert(cres == CALLRES_PENDING); 1734 lua_assert(cres == CALLRES_PENDING);
1735 J->framedepth++;
1689 return 0; /* Pending call, no result yet. */ 1736 return 0; /* Pending call, no result yet. */
1690 } 1737 }
1691 return 1; /* Result resolved immediately. */ 1738 return 1; /* Result resolved immediately. */
@@ -2213,13 +2260,13 @@ static void rec_setup_side(jit_State *J, Trace *T)
2213 } 2260 }
2214 setslot: 2261 setslot:
2215 J->slot[s] = tr | (sn&(SNAP_CONT|SNAP_FRAME)); /* Same as TREF_* flags. */ 2262 J->slot[s] = tr | (sn&(SNAP_CONT|SNAP_FRAME)); /* Same as TREF_* flags. */
2216 if ((sn & SNAP_FRAME) && s != 0) { 2263 if ((sn & SNAP_FRAME) && s != 0)
2217 J->baseslot = s+1; 2264 J->baseslot = s+1;
2218 J->framedepth++;
2219 }
2220 } 2265 }
2221 J->base = J->slot + J->baseslot; 2266 J->base = J->slot + J->baseslot;
2222 J->maxslot = snap->nslots - J->baseslot; 2267 J->maxslot = snap->nslots - J->baseslot;
2268 J->framedepth = snap->depth; /* Copy frames from snapshot. */
2269 memcpy(J->frame, &map[nent+1], sizeof(SnapEntry)*(size_t)snap->depth);
2223 lj_snap_add(J); 2270 lj_snap_add(J);
2224} 2271}
2225 2272