diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-02-27 08:52:30 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-02-27 08:52:30 -0300 |
commit | 92f6e0c1bfb27cad95d99e99912e2e0c509dcc30 (patch) | |
tree | 1ab713c16652a5a4e667457041ce7364256a6b2c /ldebug.c | |
parent | 5cd99b82b7fc11c527929e5e95f03767f6432d8e (diff) | |
download | lua-92f6e0c1bfb27cad95d99e99912e2e0c509dcc30.tar.gz lua-92f6e0c1bfb27cad95d99e99912e2e0c509dcc30.tar.bz2 lua-92f6e0c1bfb27cad95d99e99912e2e0c509dcc30.zip |
no-nonsense debug information about tail calls
Diffstat (limited to 'ldebug.c')
-rw-r--r-- | ldebug.c | 122 |
1 files changed, 65 insertions, 57 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 1.144 2003/02/11 10:46:24 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 1.145 2003/02/19 10:28:58 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -93,13 +93,21 @@ LUA_API int lua_gethookcount (lua_State *L) { | |||
93 | 93 | ||
94 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { | 94 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { |
95 | int status; | 95 | int status; |
96 | int ci; | 96 | CallInfo *ci; |
97 | lua_lock(L); | 97 | lua_lock(L); |
98 | ci = (L->ci - L->base_ci) - level; | 98 | for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { |
99 | if (ci <= 0) status = 0; /* there is no such level */ | 99 | level--; |
100 | if (!(ci->state & CI_C)) /* Lua function? */ | ||
101 | level -= ci->u.l.tailcalls; /* skip lost tail calls */ | ||
102 | } | ||
103 | if (level > 0 || ci == L->base_ci) status = 0; /* there is no such level */ | ||
104 | else if (level < 0) { /* level is of a lost tail call */ | ||
105 | status = 1; | ||
106 | ar->i_ci = 0; | ||
107 | } | ||
100 | else { | 108 | else { |
101 | ar->i_ci = ci; | ||
102 | status = 1; | 109 | status = 1; |
110 | ar->i_ci = ci - L->base_ci; | ||
103 | } | 111 | } |
104 | lua_unlock(L); | 112 | lua_unlock(L); |
105 | return status; | 113 | return status; |
@@ -150,31 +158,19 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { | |||
150 | } | 158 | } |
151 | 159 | ||
152 | 160 | ||
153 | static void infoLproto (lua_Debug *ar, Proto *f) { | ||
154 | ar->source = getstr(f->source); | ||
155 | ar->linedefined = f->lineDefined; | ||
156 | ar->what = "Lua"; | ||
157 | } | ||
158 | |||
159 | |||
160 | static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { | 161 | static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { |
161 | Closure *cl; | 162 | Closure *cl = clvalue(func); |
162 | if (ttisfunction(func)) | ||
163 | cl = clvalue(func); | ||
164 | else { | ||
165 | luaG_runerror(L, "value for `lua_getinfo' is not a function"); | ||
166 | cl = NULL; /* to avoid warnings */ | ||
167 | } | ||
168 | if (cl->c.isC) { | 163 | if (cl->c.isC) { |
169 | ar->source = "=[C]"; | 164 | ar->source = "=[C]"; |
170 | ar->linedefined = -1; | 165 | ar->linedefined = -1; |
171 | ar->what = "C"; | 166 | ar->what = "C"; |
172 | } | 167 | } |
173 | else | 168 | else { |
174 | infoLproto(ar, cl->l.p); | 169 | ar->source = getstr(cl->l.p->source); |
170 | ar->linedefined = cl->l.p->lineDefined; | ||
171 | ar->what = (ar->linedefined == 0) ? "main" : "Lua"; | ||
172 | } | ||
175 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | 173 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); |
176 | if (ar->linedefined == 0) | ||
177 | ar->what = "main"; | ||
178 | } | 174 | } |
179 | 175 | ||
180 | 176 | ||
@@ -190,29 +186,20 @@ static const char *travglobals (lua_State *L, const TObject *o) { | |||
190 | } | 186 | } |
191 | 187 | ||
192 | 188 | ||
193 | static void getname (lua_State *L, const TObject *f, lua_Debug *ar) { | 189 | static void info_tailcall (lua_State *L, lua_Debug *ar) { |
194 | /* try to find a name for given function */ | 190 | ar->name = ar->namewhat = ""; |
195 | if ((ar->name = travglobals(L, f)) != NULL) | 191 | ar->what = "tail"; |
196 | ar->namewhat = "global"; | 192 | ar->linedefined = ar->currentline = -1; |
197 | else ar->namewhat = ""; /* not found */ | 193 | ar->source = "=(tail call)"; |
194 | luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); | ||
195 | ar->nups = 0; | ||
196 | setnilvalue(L->top); | ||
198 | } | 197 | } |
199 | 198 | ||
200 | 199 | ||
201 | 200 | static int getinfo (lua_State *L, const char *what, lua_Debug *ar, | |
202 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | 201 | StkId f, CallInfo *ci) { |
203 | StkId f; | ||
204 | CallInfo *ci; | ||
205 | int status = 1; | 202 | int status = 1; |
206 | lua_lock(L); | ||
207 | if (*what != '>') { /* function is active? */ | ||
208 | ci = L->base_ci + ar->i_ci; | ||
209 | f = ci->base - 1; | ||
210 | } | ||
211 | else { | ||
212 | what++; /* skip the `>' */ | ||
213 | ci = NULL; | ||
214 | f = L->top - 1; | ||
215 | } | ||
216 | for (; *what; what++) { | 203 | for (; *what; what++) { |
217 | switch (*what) { | 204 | switch (*what) { |
218 | case 'S': { | 205 | case 'S': { |
@@ -224,25 +211,48 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
224 | break; | 211 | break; |
225 | } | 212 | } |
226 | case 'u': { | 213 | case 'u': { |
227 | ar->nups = (ttisfunction(f)) ? clvalue(f)->c.nupvalues : 0; | 214 | ar->nups = clvalue(f)->c.nupvalues; |
228 | break; | 215 | break; |
229 | } | 216 | } |
230 | case 'n': { | 217 | case 'n': { |
231 | ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL; | 218 | ar->namewhat = (ci) ? getfuncname(ci, &ar->name) : NULL; |
232 | if (ar->namewhat == NULL) | 219 | if (ar->namewhat == NULL) { |
233 | getname(L, f, ar); | 220 | /* try to find a global name */ |
221 | if ((ar->name = travglobals(L, f)) != NULL) | ||
222 | ar->namewhat = "global"; | ||
223 | else ar->namewhat = ""; /* not found */ | ||
224 | } | ||
234 | break; | 225 | break; |
235 | } | 226 | } |
236 | case 'f': { | 227 | case 'f': { |
237 | setobj2s(L->top, f); | 228 | setobj2s(L->top, f); |
238 | status = 2; | ||
239 | break; | 229 | break; |
240 | } | 230 | } |
241 | default: status = 0; /* invalid option */ | 231 | default: status = 0; /* invalid option */ |
242 | } | 232 | } |
243 | } | 233 | } |
244 | if (!ci) L->top--; /* pop function */ | 234 | return status; |
245 | if (status == 2) incr_top(L); | 235 | } |
236 | |||
237 | |||
238 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | ||
239 | int status = 1; | ||
240 | lua_lock(L); | ||
241 | if (*what == '>') { | ||
242 | StkId f = L->top - 1; | ||
243 | if (!ttisfunction(f)) | ||
244 | luaG_runerror(L, "value for `lua_getinfo' is not a function"); | ||
245 | status = getinfo(L, what + 1, ar, f, NULL); | ||
246 | L->top--; /* pop function */ | ||
247 | } | ||
248 | else if (ar->i_ci != 0) { /* no tail call? */ | ||
249 | CallInfo *ci = L->base_ci + ar->i_ci; | ||
250 | lua_assert(ttisfunction(ci->base - 1)); | ||
251 | status = getinfo(L, what, ar, ci->base - 1, ci); | ||
252 | } | ||
253 | else | ||
254 | info_tailcall(L, ar); | ||
255 | if (strchr(what, 'f')) incr_top(L); | ||
246 | lua_unlock(L); | 256 | lua_unlock(L); |
247 | return status; | 257 | return status; |
248 | } | 258 | } |
@@ -480,18 +490,16 @@ static const char *getobjname (CallInfo *ci, int stackpos, const char **name) { | |||
480 | } | 490 | } |
481 | 491 | ||
482 | 492 | ||
483 | static Instruction getcurrentinstr (CallInfo *ci) { | ||
484 | return (!isLua(ci)) ? (Instruction)(-1) : | ||
485 | ci_func(ci)->l.p->code[currentpc(ci)]; | ||
486 | } | ||
487 | |||
488 | |||
489 | static const char *getfuncname (CallInfo *ci, const char **name) { | 493 | static const char *getfuncname (CallInfo *ci, const char **name) { |
490 | Instruction i; | 494 | Instruction i; |
495 | if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1)) | ||
496 | return NULL; /* calling function is not Lua (or is unknown) */ | ||
491 | ci--; /* calling function */ | 497 | ci--; /* calling function */ |
492 | i = getcurrentinstr(ci); | 498 | i = ci_func(ci)->l.p->code[currentpc(ci)]; |
493 | return (GET_OPCODE(i) == OP_CALL ? getobjname(ci, GETARG_A(i), name) | 499 | if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL) |
494 | : NULL); /* no useful name found */ | 500 | return getobjname(ci, GETARG_A(i), name); |
501 | else | ||
502 | return NULL; /* no useful name can be found */ | ||
495 | } | 503 | } |
496 | 504 | ||
497 | 505 | ||