Skip to content

Commit f2ce363

Browse files
authored
Merge pull request #122 from ltratt/only_trace_recursive_functions
Dynamically detect recursion.
2 parents a72bcc2 + a9bc71b commit f2ce363

File tree

5 files changed

+42
-4
lines changed

5 files changed

+42
-4
lines changed

src/ldo.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,18 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func,
562562
setnilvalue(s2v(func + narg1)); /* complete missing arguments */
563563
ci->top.p = func + 1 + fsize; /* top for new function */
564564
lua_assert(ci->top.p <= L->stack_last.p);
565+
#ifdef USE_YK
566+
// If this is a recursive call and we don't yet have a yk_location,
567+
// create one now.
568+
if (p->called && yk_location_is_null(p->yklocs[0])) {
569+
p->yklocs[0] = yk_location_new();
570+
#if YKLUA_DEBUG_STRS
571+
yk_location_set_debug_str(&p->yklocs[0], p->instdebugstrs[0]);
572+
#endif
573+
} else if (!p->called) {
574+
p->called = true;
575+
}
576+
#endif
565577
ci->u.l.savedpc = p->code; /* starting point */
566578
ci->callstatus |= CIST_TAIL;
567579
L->top.p = func + narg1; /* set top */
@@ -606,6 +618,18 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) {
606618
for (; narg < nfixparams; narg++)
607619
setnilvalue(s2v(L->top.p++)); /* complete missing arguments */
608620
lua_assert(ci->top.p <= L->stack_last.p);
621+
#ifdef USE_YK
622+
// If this is a recursive call and we don't yet have a yk_location,
623+
// create one now.
624+
if (p->called && yk_location_is_null(p->yklocs[0])) {
625+
p->yklocs[0] = yk_location_new();
626+
#if YKLUA_DEBUG_STRS
627+
yk_location_set_debug_str(&p->yklocs[0], p->instdebugstrs[0]);
628+
#endif
629+
} else if (!p->called) {
630+
p->called = true;
631+
}
632+
#endif
609633
return ci;
610634
}
611635
default: { /* not a function */

src/lfunc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ Proto *luaF_newproto (lua_State *L) {
264264
f->lastlinedefined = 0;
265265
f->source = NULL;
266266
#ifdef USE_YK
267+
f->called = false;
267268
f->yklocs = NULL;
268269
#ifdef YKLUA_DEBUG_STRS
269270
f->instdebugstrs = NULL;

src/lobject.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,13 @@ typedef struct Proto {
569569
TValue *k; /* constants used by the function */
570570
Instruction *code; /* opcodes */
571571
#ifdef USE_YK
572+
/* Used to detect recursive function calls. When a function is
573+
* called this is set to `true` and when we return it is set to `false`. This
574+
* works because a recursive function call must detect the `true` case before
575+
* the bit is flipped. In other words, `called` being `false` does not mean
576+
* "this isn't a recursive call", but if it's `true` it definitely is a
577+
* recursive call. */
578+
bool called;
572579
YkLocation *yklocs; /* One 'YkLocation' per instruction in 'code' */
573580
#ifdef YKLUA_DEBUG_STRS
574581
char **instdebugstrs; /* One `char *` per instruction in `code` */

src/lparser.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -832,15 +832,18 @@ void ykifyCode(lua_State *L, Proto *f, int num_insts) {
832832
char *dstr = luaG_ykdebug_str(f, pc);
833833
f->instdebugstrs[pc] = dstr;
834834
#endif
835+
if (pc == 0) {
836+
// We only insert locations for the start of functions when we
837+
// dynamically detect that a function is definitely recursive. See
838+
// luaD_precall.
839+
continue;
840+
}
835841
/*
836842
* The computation for finding the start of loops is derived from
837843
* `PrintCode()` in `luac.c`.
838844
*/
839845
int loc_pc;
840-
if (pc == 0) {
841-
// We always add a ykloc to the first instruction.
842-
loc_pc = 0;
843-
} else if ((GET_OPCODE(i) == OP_JMP) && (GETARG_sJ(i) < 0)) {
846+
if ((GET_OPCODE(i) == OP_JMP) && (GETARG_sJ(i) < 0)) {
844847
lua_assert(GETARG_sJ(i) + pc + 2 - 1 < pc);
845848
loc_pc = GETARG_sJ(i) + pc + 2 - 1;
846849
} else if (GET_OPCODE(i) == OP_FORLOOP) {

src/lvm.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,9 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
18531853
}
18541854
}
18551855
ret: /* return from a Lua function */
1856+
#ifdef USE_YK
1857+
cl->p->called = false;
1858+
#endif
18561859
if (ci->callstatus & CIST_FRESH)
18571860
return; /* end this frame */
18581861
else {

0 commit comments

Comments
 (0)