diff options
Diffstat (limited to 'src/ldebug.c')
-rw-r--r--[-rwxr-xr-x] | src/ldebug.c | 204 |
1 files changed, 106 insertions, 98 deletions
diff --git a/src/ldebug.c b/src/ldebug.c index a2565cf..31b7ae4 100755..100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.82 2011/06/02 19:31:40 roberto Exp $ +** $Id: ldebug.c,v 2.88 2011/11/30 12:43:51 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -94,6 +94,13 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { } +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); +} + + static const char *findvararg (CallInfo *ci, int n, StkId *pos) { int nparams = clLvalue(ci->func)->p->numparams; if (n >= ci->u.l.base - ci->func - nparams) @@ -190,12 +197,14 @@ static void collectvalidlines (lua_State *L, Closure *f) { } else { int i; + TValue v; int *lineinfo = f->l.p->lineinfo; - Table *t = luaH_new(L); - sethvalue(L, L->top, t); + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ incr_top(L); - for (i=0; i<f->l.p->sizelineinfo; i++) - setbvalue(luaH_setint(L, t, lineinfo[i]), 1); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ } } @@ -230,7 +239,11 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'n': { - ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + /* calling function is a known Lua function? */ + if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + ar->namewhat = getfuncname(L, ci->previous, &ar->name); + else + ar->namewhat = NULL; if (ar->namewhat == NULL) { ar->namewhat = ""; /* not found */ ar->name = NULL; @@ -284,17 +297,16 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { ** ======================================================= */ -static const char *getobjname (lua_State *L, CallInfo *ci, int reg, +static const char *getobjname (Proto *p, int lastpc, int reg, const char **name); /* ** find a "name" for the RK value 'c' */ -static void kname (lua_State *L, CallInfo *ci, int c, int oreg, - const char *what, const char **name) { +static void kname (Proto *p, int pc, int c, const char **name) { if (ISK(c)) { /* is 'c' a constant? */ - TValue *kvalue = &ci_func(ci)->p->k[INDEXK(c)]; + TValue *kvalue = &p->k[INDEXK(c)]; if (ttisstring(kvalue)) { /* literal constant? */ *name = svalue(kvalue); /* it is its own name */ return; @@ -302,8 +314,7 @@ static void kname (lua_State *L, CallInfo *ci, int c, int oreg, /* else no reasonable name found */ } else { /* 'c' is a register */ - if (c != oreg) /* not the original register? */ - what = getobjname(L, ci, c, name); /* search for 'c' */ + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ if (what && *what == 'c') { /* found a constant name? */ return; /* 'name' already filled */ } @@ -313,85 +324,30 @@ static void kname (lua_State *L, CallInfo *ci, int c, int oreg, } -static const char *getobjname (lua_State *L, CallInfo *ci, int reg, - const char **name) { - Proto *p = ci_func(ci)->p; - const char *what = NULL; - int lastpc = currentpc(ci); +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, int lastpc, int reg) { int pc; - *name = luaF_getlocalname(p, reg + 1, lastpc); - if (*name) /* is a local? */ - return "local"; - /* else try symbolic execution */ + int setreg = -1; /* keep last instruction that changed 'reg' */ for (pc = 0; pc < lastpc; pc++) { Instruction i = p->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); switch (op) { - case OP_MOVE: { - if (reg == a) { - int b = GETARG_B(i); /* move from 'b' to 'a' */ - if (b < a) - what = getobjname(L, ci, b, name); /* get name for 'b' */ - else what = NULL; - } - break; - } - case OP_GETTABUP: - case OP_GETTABLE: { - if (reg == a) { - int k = GETARG_C(i); /* key index */ - int t = GETARG_B(i); - const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ - ? luaF_getlocalname(p, t + 1, pc) - : getstr(p->upvalues[t].name); - kname(L, ci, k, a, what, name); - what = (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; - } - break; - } - case OP_GETUPVAL: { - if (reg == a) { - int u = GETARG_B(i); /* upvalue index */ - TString *tn = p->upvalues[u].name; - *name = tn ? getstr(tn) : "?"; - what = "upvalue"; - } - break; - } - case OP_LOADK: - case OP_LOADKX: { - if (reg == a) { - int b = (op == OP_LOADK) ? GETARG_Bx(i) - : GETARG_Ax(p->code[pc + 1]); - if (ttisstring(&p->k[b])) { - what = "constant"; - *name = svalue(&p->k[b]); - } - } - break; - } case OP_LOADNIL: { int b = GETARG_B(i); if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ - what = NULL; - break; - } - case OP_SELF: { - if (reg == a) { - int k = GETARG_C(i); /* key index */ - kname(L, ci, k, a, what, name); - what = "method"; - } + setreg = pc; break; } case OP_TFORCALL: { - if (reg >= a + 2) what = NULL; /* affect all regs above its base */ + if (reg >= a + 2) setreg = pc; /* affect all regs above its base */ break; } case OP_CALL: case OP_TAILCALL: { - if (reg >= a) what = NULL; /* affect all registers above base */ + if (reg >= a) setreg = pc; /* affect all registers above base */ break; } case OP_JMP: { @@ -403,35 +359,87 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int reg, break; } case OP_TEST: { - if (reg == a) what = NULL; /* jumped code can change 'a' */ + if (reg == a) setreg = pc; /* jumped code can change 'a' */ break; } default: - if (testAMode(op) && reg == a) what = NULL; + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = pc; break; } } - return what; + return setreg; +} + + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name) { + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_MOVE: { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + int t = GETARG_B(i); /* table index */ + const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; + } + case OP_GETUPVAL: { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + kname(p, pc, k, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ } static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { TMS tm; - Instruction i; - if ((ci->callstatus & CIST_TAIL) || !isLua(ci->previous)) - return NULL; /* calling function is not Lua (or is unknown) */ - ci = ci->previous; /* calling function */ - i = ci_func(ci)->p->code[currentpc(ci)]; - if (GET_OPCODE(i) == OP_EXTRAARG) /* extra argument? */ - i = ci_func(ci)->p->code[currentpc(ci) - 1]; /* get 'real' instruction */ + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ switch (GET_OPCODE(i)) { case OP_CALL: - case OP_TAILCALL: - return getobjname(L, ci, GETARG_A(i), name); - case OP_TFORCALL: { + case OP_TAILCALL: /* get function name */ + return getobjname(p, pc, GETARG_A(i), name); + case OP_TFORCALL: { /* for iterator */ *name = "for iterator"; return "for iterator"; } + /* all other instructions can call only through metamethods */ case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: tm = TM_INDEX; break; @@ -473,12 +481,12 @@ static int isinstack (CallInfo *ci, const TValue *o) { static const char *getupvalname (CallInfo *ci, const TValue *o, - const char **name) { + const char **name) { LClosure *c = ci_func(ci); int i; for (i = 0; i < c->nupvalues; i++) { if (c->upvals[i]->v == o) { - *name = getstr(c->p->upvalues[i].name); + *name = upvalname(c->p, i); return "upvalue"; } } @@ -486,7 +494,7 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, } -void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { CallInfo *ci = L->ci; const char *name = NULL; const char *t = objtypename(o); @@ -494,7 +502,8 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { if (isLua(ci)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(L, ci, cast_int(o - ci->u.l.base), &name); + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); } if (kind) luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", @@ -504,14 +513,14 @@ void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { } -void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { +l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2) { if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; lua_assert(!ttisstring(p1) && !ttisnumber(p2)); luaG_typeerror(L, p1, "concatenate"); } -void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { +l_noret luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { TValue temp; if (luaV_tonumber(p1, &temp) == NULL) p2 = p1; /* first operand is wrong */ @@ -519,14 +528,13 @@ void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { } -int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { const char *t1 = objtypename(p1); const char *t2 = objtypename(p2); if (t1 == t2) luaG_runerror(L, "attempt to compare two %s values", t1); else luaG_runerror(L, "attempt to compare %s with %s", t1, t2); - return 0; } @@ -546,7 +554,7 @@ static void addinfo (lua_State *L, const char *msg) { } -void luaG_errormsg (lua_State *L) { +l_noret luaG_errormsg (lua_State *L) { if (L->errfunc != 0) { /* is there an error handling function? */ StkId errfunc = restorestack(L, L->errfunc); if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); @@ -559,7 +567,7 @@ void luaG_errormsg (lua_State *L) { } -void luaG_runerror (lua_State *L, const char *fmt, ...) { +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); addinfo(L, luaO_pushvfstring(L, fmt, argp)); |