diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-11-25 13:27:51 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2009-11-25 13:27:51 -0200 |
commit | b0f2b288a6b860374b9578d4c51329fc9cd43022 (patch) | |
tree | 82bacf246458c8f97ec22424ff40832df67a52e5 /ldo.c | |
parent | 2b25489b47ad94e6f970f5d9150937734322f24c (diff) | |
download | lua-b0f2b288a6b860374b9578d4c51329fc9cd43022.tar.gz lua-b0f2b288a6b860374b9578d4c51329fc9cd43022.tar.bz2 lua-b0f2b288a6b860374b9578d4c51329fc9cd43022.zip |
new scheme for debug info about tail calls: no more 'fake' stack entries,
but stack entry knows whether it was tail called
Diffstat (limited to 'ldo.c')
-rw-r--r-- | ldo.c | 54 |
1 files changed, 26 insertions, 28 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.71 2009/11/17 16:33:38 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.72 2009/11/17 16:46:44 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 | */ |
@@ -184,7 +184,7 @@ void luaD_shrinkstack (lua_State *L) { | |||
184 | } | 184 | } |
185 | 185 | ||
186 | 186 | ||
187 | void luaD_callhook (lua_State *L, int event, int line) { | 187 | void luaD_hook (lua_State *L, int event, int line) { |
188 | lua_Hook hook = L->hook; | 188 | lua_Hook hook = L->hook; |
189 | if (hook && L->allowhook) { | 189 | if (hook && L->allowhook) { |
190 | CallInfo *ci = L->ci; | 190 | CallInfo *ci = L->ci; |
@@ -193,10 +193,7 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
193 | lua_Debug ar; | 193 | lua_Debug ar; |
194 | ar.event = event; | 194 | ar.event = event; |
195 | ar.currentline = line; | 195 | ar.currentline = line; |
196 | if (event == LUA_HOOKTAILRET) | 196 | ar.i_ci = ci; |
197 | ar.i_ci = NULL; /* tail call; no debug information about it */ | ||
198 | else | ||
199 | ar.i_ci = ci; | ||
200 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 197 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
201 | ci->top = L->top + LUA_MINSTACK; | 198 | ci->top = L->top + LUA_MINSTACK; |
202 | lua_assert(ci->top <= L->stack_last); | 199 | lua_assert(ci->top <= L->stack_last); |
@@ -214,6 +211,19 @@ void luaD_callhook (lua_State *L, int event, int line) { | |||
214 | } | 211 | } |
215 | 212 | ||
216 | 213 | ||
214 | static void callhook (lua_State *L, CallInfo *ci) { | ||
215 | int hook = LUA_HOOKCALL; | ||
216 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | ||
217 | if (isLua(ci->previous) && | ||
218 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { | ||
219 | ci->callstatus |= CIST_TAIL; | ||
220 | hook = LUA_HOOKTAILCALL; | ||
221 | } | ||
222 | luaD_hook(L, hook, -1); | ||
223 | ci->u.l.savedpc--; /* correct 'pc' */ | ||
224 | } | ||
225 | |||
226 | |||
217 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { | 227 | static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { |
218 | int i; | 228 | int i; |
219 | int nfixargs = p->numparams; | 229 | int nfixargs = p->numparams; |
@@ -281,14 +291,10 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
281 | ci->top = base + p->maxstacksize; | 291 | ci->top = base + p->maxstacksize; |
282 | lua_assert(ci->top <= L->stack_last); | 292 | lua_assert(ci->top <= L->stack_last); |
283 | ci->u.l.savedpc = p->code; /* starting point */ | 293 | ci->u.l.savedpc = p->code; /* starting point */ |
284 | ci->u.l.tailcalls = 0; | ||
285 | ci->callstatus = CIST_LUA; | 294 | ci->callstatus = CIST_LUA; |
286 | L->top = ci->top; | 295 | L->top = ci->top; |
287 | if (L->hookmask & LUA_MASKCALL) { | 296 | if (L->hookmask & LUA_MASKCALL) |
288 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 297 | callhook(L, ci); |
289 | luaD_callhook(L, LUA_HOOKCALL, -1); | ||
290 | ci->u.l.savedpc--; /* correct 'pc' */ | ||
291 | } | ||
292 | return 0; | 298 | return 0; |
293 | } | 299 | } |
294 | else { /* if is a C function, call it */ | 300 | else { /* if is a C function, call it */ |
@@ -301,7 +307,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
301 | lua_assert(ci->top <= L->stack_last); | 307 | lua_assert(ci->top <= L->stack_last); |
302 | ci->callstatus = 0; | 308 | ci->callstatus = 0; |
303 | if (L->hookmask & LUA_MASKCALL) | 309 | if (L->hookmask & LUA_MASKCALL) |
304 | luaD_callhook(L, LUA_HOOKCALL, -1); | 310 | luaD_hook(L, LUA_HOOKCALL, -1); |
305 | lua_unlock(L); | 311 | lua_unlock(L); |
306 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ | 312 | n = (*curr_func(L)->c.f)(L); /* do the actual call */ |
307 | lua_lock(L); | 313 | lua_lock(L); |
@@ -311,25 +317,17 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
311 | } | 317 | } |
312 | 318 | ||
313 | 319 | ||
314 | static StkId callrethooks (lua_State *L, StkId firstResult) { | ||
315 | ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ | ||
316 | luaD_callhook(L, LUA_HOOKRET, -1); | ||
317 | if (isLua(L->ci)) { /* Lua function? */ | ||
318 | while ((L->hookmask & LUA_MASKRET) && L->ci->u.l.tailcalls--) | ||
319 | luaD_callhook(L, LUA_HOOKTAILRET, -1); /* ret. hooks for tail calls */ | ||
320 | } | ||
321 | return restorestack(L, fr); | ||
322 | } | ||
323 | |||
324 | |||
325 | int luaD_poscall (lua_State *L, StkId firstResult) { | 320 | int luaD_poscall (lua_State *L, StkId firstResult) { |
326 | StkId res; | 321 | StkId res; |
327 | int wanted, i; | 322 | int wanted, i; |
328 | CallInfo *ci = L->ci; | 323 | CallInfo *ci = L->ci; |
329 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { | 324 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { |
330 | if (L->hookmask & LUA_MASKRET) | 325 | if (L->hookmask & LUA_MASKRET) { |
331 | firstResult = callrethooks(L, firstResult); | 326 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ |
332 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for returning function */ | 327 | luaD_hook(L, LUA_HOOKRET, -1); |
328 | firstResult = restorestack(L, fr); | ||
329 | } | ||
330 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ | ||
333 | } | 331 | } |
334 | res = ci->func; /* res == final position of 1st result */ | 332 | res = ci->func; /* res == final position of 1st result */ |
335 | L->ci = ci = ci->previous; /* back to caller */ | 333 | L->ci = ci = ci->previous; /* back to caller */ |
@@ -529,7 +527,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { | |||
529 | } | 527 | } |
530 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ | 528 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ |
531 | lua_unlock(L); | 529 | lua_unlock(L); |
532 | return 0; /* otherwise, return to 'luaD_callhook' */ | 530 | return 0; /* return to 'luaD_hook' */ |
533 | } | 531 | } |
534 | 532 | ||
535 | 533 | ||