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 | |
| parent | 5cd99b82b7fc11c527929e5e95f03767f6432d8e (diff) | |
| download | lua-92f6e0c1bfb27cad95d99e99912e2e0c509dcc30.tar.gz lua-92f6e0c1bfb27cad95d99e99912e2e0c509dcc30.tar.bz2 lua-92f6e0c1bfb27cad95d99e99912e2e0c509dcc30.zip | |
no-nonsense debug information about tail calls
| -rw-r--r-- | lbaselib.c | 5 | ||||
| -rw-r--r-- | ldblib.c | 9 | ||||
| -rw-r--r-- | ldebug.c | 122 | ||||
| -rw-r--r-- | ldo.c | 27 | ||||
| -rw-r--r-- | lstate.h | 3 | ||||
| -rw-r--r-- | lua.h | 5 | ||||
| -rw-r--r-- | lvm.c | 3 |
7 files changed, 101 insertions, 73 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lbaselib.c,v 1.122 2003/02/24 16:50:41 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.123 2003/02/24 16:54:20 roberto Exp roberto $ |
| 3 | ** Basic library | 3 | ** Basic library |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -123,6 +123,9 @@ static void getfunc (lua_State *L) { | |||
| 123 | if (lua_getstack(L, level, &ar) == 0) | 123 | if (lua_getstack(L, level, &ar) == 0) |
| 124 | luaL_argerror(L, 1, "invalid level"); | 124 | luaL_argerror(L, 1, "invalid level"); |
| 125 | lua_getinfo(L, "f", &ar); | 125 | lua_getinfo(L, "f", &ar); |
| 126 | if (lua_isnil(L, -1)) | ||
| 127 | luaL_error(L, "cannot get/set environment (tail call at level %d)", | ||
| 128 | level); | ||
| 126 | } | 129 | } |
| 127 | } | 130 | } |
| 128 | 131 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldblib.c,v 1.76 2002/12/19 11:11:55 roberto Exp roberto $ | 2 | ** $Id: ldblib.c,v 1.77 2002/12/20 10:26:33 roberto Exp roberto $ |
| 3 | ** Interface from Lua to its debug API | 3 | ** Interface from Lua to its debug API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -137,7 +137,8 @@ static const char KEY_HOOK = 'h'; | |||
| 137 | 137 | ||
| 138 | 138 | ||
| 139 | static void hookf (lua_State *L, lua_Debug *ar) { | 139 | static void hookf (lua_State *L, lua_Debug *ar) { |
| 140 | static const char *const hooknames[] = {"call", "return", "line", "count"}; | 140 | static const char *const hooknames[] = |
| 141 | {"call", "return", "line", "count", "tail return"}; | ||
| 141 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); | 142 | lua_pushlightuserdata(L, (void *)&KEY_HOOK); |
| 142 | lua_rawget(L, LUA_REGISTRYINDEX); | 143 | lua_rawget(L, LUA_REGISTRYINDEX); |
| 143 | if (lua_isfunction(L, -1)) { | 144 | if (lua_isfunction(L, -1)) { |
| @@ -259,8 +260,8 @@ static int errorfb (lua_State *L) { | |||
| 259 | default: { | 260 | default: { |
| 260 | if (*ar.what == 'm') /* main? */ | 261 | if (*ar.what == 'm') /* main? */ |
| 261 | lua_pushfstring(L, " in main chunk"); | 262 | lua_pushfstring(L, " in main chunk"); |
| 262 | else if (*ar.what == 'C') /* C function? */ | 263 | else if (*ar.what == 'C' || *ar.what == 't') |
| 263 | lua_pushfstring(L, "%s", ar.short_src); | 264 | lua_pushliteral(L, " ?"); /* C function or tail call */ |
| 264 | else | 265 | else |
| 265 | lua_pushfstring(L, " in function <%s:%d>", | 266 | lua_pushfstring(L, " in function <%s:%d>", |
| 266 | ar.short_src, ar.linedefined); | 267 | ar.short_src, ar.linedefined); |
| @@ -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 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldo.c,v 1.212 2003/01/23 11:31:38 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 1.213 2003/02/13 16:08:47 roberto Exp roberto $ |
| 3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -31,6 +31,7 @@ | |||
| 31 | 31 | ||
| 32 | 32 | ||
| 33 | 33 | ||
| 34 | |||
| 34 | /* | 35 | /* |
| 35 | ** {====================================================== | 36 | ** {====================================================== |
| 36 | ** Error-recovery functions (based on long jumps) | 37 | ** Error-recovery functions (based on long jumps) |
| @@ -161,7 +162,10 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
| 161 | lua_Debug ar; | 162 | lua_Debug ar; |
| 162 | ar.event = event; | 163 | ar.event = event; |
| 163 | ar.currentline = line; | 164 | ar.currentline = line; |
| 164 | ar.i_ci = L->ci - L->base_ci; | 165 | if (event == LUA_HOOKTAILRET) |
| 166 | ar.i_ci = 0; /* tail call; no debug information about it */ | ||
| 167 | else | ||
| 168 | ar.i_ci = L->ci - L->base_ci; | ||
| 165 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 169 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
| 166 | L->ci->top = L->top + LUA_MINSTACK; | 170 | L->ci->top = L->top + LUA_MINSTACK; |
| 167 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 171 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
| @@ -232,6 +236,7 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 232 | L->base = L->ci->base = restorestack(L, funcr) + 1; | 236 | L->base = L->ci->base = restorestack(L, funcr) + 1; |
| 233 | ci->top = L->base + p->maxstacksize; | 237 | ci->top = L->base + p->maxstacksize; |
| 234 | ci->u.l.savedpc = p->code; /* starting point */ | 238 | ci->u.l.savedpc = p->code; /* starting point */ |
| 239 | ci->u.l.tailcalls = 0; | ||
| 235 | ci->state = CI_SAVEDPC; | 240 | ci->state = CI_SAVEDPC; |
| 236 | while (L->top < ci->top) | 241 | while (L->top < ci->top) |
| 237 | setnilvalue(L->top++); | 242 | setnilvalue(L->top++); |
| @@ -261,13 +266,21 @@ StkId luaD_precall (lua_State *L, StkId func) { | |||
| 261 | } | 266 | } |
| 262 | 267 | ||
| 263 | 268 | ||
| 269 | static StkId callrethooks (lua_State *L, StkId firstResult) { | ||
| 270 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ | ||
| 271 | luaD_callhook(L, LUA_HOOKRET, -1); | ||
| 272 | if (!(L->ci->state & CI_C)) { /* Lua function? */ | ||
| 273 | while (L->ci->u.l.tailcalls--) /* call hook for eventual tail calls */ | ||
| 274 | luaD_callhook(L, LUA_HOOKTAILRET, -1); | ||
| 275 | } | ||
| 276 | return restorestack(L, fr); | ||
| 277 | } | ||
| 278 | |||
| 279 | |||
| 264 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { | 280 | void luaD_poscall (lua_State *L, int wanted, StkId firstResult) { |
| 265 | StkId res; | 281 | StkId res; |
| 266 | if (L->hookmask & LUA_MASKRET) { | 282 | if (L->hookmask & LUA_MASKRET) |
| 267 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ | 283 | firstResult = callrethooks(L, firstResult); |
| 268 | luaD_callhook(L, LUA_HOOKRET, -1); | ||
| 269 | firstResult = restorestack(L, fr); | ||
| 270 | } | ||
| 271 | res = L->base - 1; /* res == final position of 1st result */ | 284 | res = L->base - 1; /* res == final position of 1st result */ |
| 272 | L->ci--; | 285 | L->ci--; |
| 273 | L->base = L->ci->base; /* restore base */ | 286 | L->base = L->ci->base; /* restore base */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 1.107 2002/11/22 18:01:46 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.108 2002/11/25 17:47:13 roberto Exp roberto $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -80,6 +80,7 @@ typedef struct CallInfo { | |||
| 80 | struct { /* for Lua functions */ | 80 | struct { /* for Lua functions */ |
| 81 | const Instruction *savedpc; | 81 | const Instruction *savedpc; |
| 82 | const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ | 82 | const Instruction **pc; /* points to `pc' variable in `luaV_execute' */ |
| 83 | int tailcalls; /* number of tail calls lost under this entry */ | ||
| 83 | } l; | 84 | } l; |
| 84 | struct { /* for C functions */ | 85 | struct { /* for C functions */ |
| 85 | int dummy; /* just to avoid an empty struct */ | 86 | int dummy; /* just to avoid an empty struct */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lua.h,v 1.172 2003/02/18 16:13:15 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.173 2003/02/24 16:54:20 roberto Exp roberto $ |
| 3 | ** Lua - An Extensible Extension Language | 3 | ** Lua - An Extensible Extension Language |
| 4 | ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil | 4 | ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil |
| 5 | ** http://www.lua.org mailto:info@lua.org | 5 | ** http://www.lua.org mailto:info@lua.org |
| @@ -317,6 +317,7 @@ LUA_API int lua_pushupvalues (lua_State *L); | |||
| 317 | #define LUA_HOOKRET 1 | 317 | #define LUA_HOOKRET 1 |
| 318 | #define LUA_HOOKLINE 2 | 318 | #define LUA_HOOKLINE 2 |
| 319 | #define LUA_HOOKCOUNT 3 | 319 | #define LUA_HOOKCOUNT 3 |
| 320 | #define LUA_HOOKTAILRET 4 | ||
| 320 | 321 | ||
| 321 | 322 | ||
| 322 | /* | 323 | /* |
| @@ -351,7 +352,7 @@ struct lua_Debug { | |||
| 351 | int event; | 352 | int event; |
| 352 | const char *name; /* (n) */ | 353 | const char *name; /* (n) */ |
| 353 | const char *namewhat; /* (n) `global', `local', `field', `method' */ | 354 | const char *namewhat; /* (n) `global', `local', `field', `method' */ |
| 354 | const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ | 355 | const char *what; /* (S) `Lua', `C', `main', `tail' */ |
| 355 | const char *source; /* (S) */ | 356 | const char *source; /* (S) */ |
| 356 | int currentline; /* (l) */ | 357 | int currentline; /* (l) */ |
| 357 | int nups; /* (u) number of upvalues */ | 358 | int nups; /* (u) number of upvalues */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 1.275 2003/02/11 10:46:24 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.276 2003/02/18 16:02:56 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -648,6 +648,7 @@ StkId luaV_execute (lua_State *L) { | |||
| 648 | (L->ci - 1)->top = L->top = base+aux; /* correct top */ | 648 | (L->ci - 1)->top = L->top = base+aux; /* correct top */ |
| 649 | lua_assert(L->ci->state & CI_SAVEDPC); | 649 | lua_assert(L->ci->state & CI_SAVEDPC); |
| 650 | (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; | 650 | (L->ci - 1)->u.l.savedpc = L->ci->u.l.savedpc; |
| 651 | (L->ci - 1)->u.l.tailcalls++; /* one more call lost */ | ||
| 651 | (L->ci - 1)->state = CI_SAVEDPC; | 652 | (L->ci - 1)->state = CI_SAVEDPC; |
| 652 | L->ci--; /* remove new frame */ | 653 | L->ci--; /* remove new frame */ |
| 653 | L->base = L->ci->base; | 654 | L->base = L->ci->base; |
