Browse Source

new implementation for 'getobjname': first search for relevant
instruction (new function 'findsetreg') and then try to build
a meaningful name

Roberto Ierusalimschy 14 years ago
parent
commit
0b65cb74cd
1 changed files with 87 additions and 85 deletions
  1. 87 85
      ldebug.c

+ 87 - 85
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.82 2011/06/02 19:31:40 roberto Exp roberto $
+** $Id: ldebug.c,v 2.83 2011/08/09 20:58:29 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -232,7 +232,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;
@@ -286,17 +290,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;
@@ -304,8 +307,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 */
     }
@@ -315,85 +317,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: {
@@ -405,35 +352,89 @@ 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);
+    int a = GETARG_A(i);
+    switch (op) {
+      case OP_MOVE: {
+        int b = GETARG_B(i);  /* move from 'b' to 'a' */
+        lua_assert(reg == a);
+        if (b < a)
+          return getobjname(p, pc, b, name);  /* get name for 'b' */
+      }
+      case OP_GETTABUP:
+      case OP_GETTABLE: {
+        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(p, pc, k, name);
+        return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field";
+      }
+      case OP_GETUPVAL: {
+        int u = GETARG_B(i);  /* upvalue index */
+        TString *tn = p->upvalues[u].name;
+        *name = tn ? getstr(tn) : "?";
+        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";
+        }
+      }
+      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;
@@ -496,7 +497,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)",