From 92f6e0c1bfb27cad95d99e99912e2e0c509dcc30 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 27 Feb 2003 08:52:30 -0300 Subject: no-nonsense debug information about tail calls --- ldebug.c | 122 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 65 insertions(+), 57 deletions(-) (limited to 'ldebug.c') diff --git a/ldebug.c b/ldebug.c index 39b27810..e308e080 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.144 2003/02/11 10:46:24 roberto Exp roberto $ +** $Id: ldebug.c,v 1.145 2003/02/19 10:28:58 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -93,13 +93,21 @@ LUA_API int lua_gethookcount (lua_State *L) { LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { int status; - int ci; + CallInfo *ci; lua_lock(L); - ci = (L->ci - L->base_ci) - level; - if (ci <= 0) status = 0; /* there is no such level */ + for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + level--; + if (!(ci->state & CI_C)) /* Lua function? */ + level -= ci->u.l.tailcalls; /* skip lost tail calls */ + } + if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ + else if (level < 0) { /* level is of a lost tail call */ + status = 1; + ar->i_ci = 0; + } else { - ar->i_ci = ci; status = 1; + ar->i_ci = ci - L->base_ci; } lua_unlock(L); return status; @@ -150,31 +158,19 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { } -static void infoLproto (lua_Debug *ar, Proto *f) { - ar->source = getstr(f->source); - ar->linedefined = f->lineDefined; - ar->what = "Lua"; -} - - static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { - Closure *cl; - if (ttisfunction(func)) - cl = clvalue(func); - else { - luaG_runerror(L, "value for `lua_getinfo' is not a function"); - cl = NULL; /* to avoid warnings */ - } + Closure *cl = clvalue(func); if (cl->c.isC) { ar->source = "=[C]"; ar->linedefined = -1; ar->what = "C"; } - else - infoLproto(ar, cl->l.p); + else { + ar->source = getstr(cl->l.p->source); + ar->linedefined = cl->l.p->lineDefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); - if (ar->linedefined == 0) - ar->what = "main"; } @@ -190,29 +186,20 @@ static const char *travglobals (lua_State *L, const TObject *o) { } -static void getname (lua_State *L, const TObject *f, lua_Debug *ar) { - /* try to find a name for given function */ - if ((ar->name = travglobals(L, f)) != NULL) - ar->namewhat = "global"; - else ar->namewhat = ""; /* not found */ +static void info_tailcall (lua_State *L, lua_Debug *ar) { + ar->name = ar->namewhat = ""; + ar->what = "tail"; + ar->linedefined = ar->currentline = -1; + ar->source = "=(tail call)"; + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); + ar->nups = 0; + setnilvalue(L->top); } - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - StkId f; - CallInfo *ci; +static int getinfo (lua_State *L, const char *what, lua_Debug *ar, + StkId f, CallInfo *ci) { int status = 1; - lua_lock(L); - if (*what != '>') { /* function is active? */ - ci = L->base_ci + ar->i_ci; - f = ci->base - 1; - } - else { - what++; /* skip the `>' */ - ci = NULL; - f = L->top - 1; - } for (; *what; what++) { switch (*what) { case 'S': { @@ -224,25 +211,48 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { break; } case 'u': { - ar->nups = (ttisfunction(f)) ? clvalue(f)->c.nupvalues : 0; + ar->nups = clvalue(f)->c.nupvalues; break; } case 'n': { ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL; - if (ar->namewhat == NULL) - getname(L, f, ar); + if (ar->namewhat == NULL) { + /* try to find a global name */ + if ((ar->name = travglobals(L, f)) != NULL) + ar->namewhat = "global"; + else ar->namewhat = ""; /* not found */ + } break; } case 'f': { setobj2s(L->top, f); - status = 2; break; } default: status = 0; /* invalid option */ } } - if (!ci) L->top--; /* pop function */ - if (status == 2) incr_top(L); + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status = 1; + lua_lock(L); + if (*what == '>') { + StkId f = L->top - 1; + if (!ttisfunction(f)) + luaG_runerror(L, "value for `lua_getinfo' is not a function"); + status = getinfo(L, what + 1, ar, f, NULL); + L->top--; /* pop function */ + } + else if (ar->i_ci != 0) { /* no tail call? */ + CallInfo *ci = L->base_ci + ar->i_ci; + lua_assert(ttisfunction(ci->base - 1)); + status = getinfo(L, what, ar, ci->base - 1, ci); + } + else + info_tailcall(L, ar); + if (strchr(what, 'f')) incr_top(L); lua_unlock(L); return status; } @@ -480,18 +490,16 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) { } -static Instruction getcurrentinstr (CallInfo *ci) { - return (!isLua(ci)) ? (Instruction)(-1) : - ci_func(ci)->l.p->code[currentpc(ci)]; -} - - static const char *getfuncname (CallInfo *ci, const char **name) { Instruction i; + if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1)) + return NULL; /* calling function is not Lua (or is unknown) */ ci--; /* calling function */ - i = getcurrentinstr(ci); - return (GET_OPCODE(i) == OP_CALL ? getobjname(ci, GETARG_A(i), name) - : NULL); /* no useful name found */ + i = ci_func(ci)->l.p->code[currentpc(ci)]; + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL) + return getobjname(ci, GETARG_A(i), name); + else + return NULL; /* no useful name can be found */ } -- cgit v1.2.3-55-g6feb