From 43013b39cc28e873e18207e8e7259b6b90fed06b Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 18 Nov 2002 09:01:55 -0200 Subject: [PATCH] new representation for hooks (to allow asynchronous calls to sethook) --- ldebug.c | 35 ++++++++++++++++++++++------------- ldebug.h | 8 +++----- ldo.c | 20 ++++++++++---------- lgc.c | 8 ++++---- lstate.c | 7 ++++--- lstate.h | 7 +++++-- lua.h | 10 +++++----- lvm.c | 8 ++++++-- 8 files changed, 59 insertions(+), 44 deletions(-) diff --git a/ldebug.c b/ldebug.c index 91a3fc95..798d7eea 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 1.135 2002/10/16 20:40:58 roberto Exp roberto $ +** $Id: ldebug.c,v 1.136 2002/11/07 15:37:10 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -49,20 +49,29 @@ static int currentline (CallInfo *ci) { } -LUA_API int lua_sethook (lua_State *L, lua_Hook func, unsigned long mask) { - int allow; +void luaG_inithooks (lua_State *L) { CallInfo *ci; - lua_lock(L); - allow = allowhook(L); - if (func == NULL) mask = 0; - else if (mask == 0) func = NULL; - L->hook = func; - L->hookmask = mask; - setallowhook(L, allow); - resethookcount(L); for (ci = L->ci; ci != L->base_ci; ci--) /* update all `savedpc's */ currentpc(ci); - lua_unlock(L); + L->hookinit = 1; +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API int lua_sethook (lua_State *L, lua_Hook func, unsigned long mask) { + ls_count count = lua_getmaskcount(mask); + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + else if (count > 0) mask |= (1<hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast(lu_byte, mask & 0xf); + L->hookinit = 0; return 1; } @@ -73,7 +82,7 @@ LUA_API lua_Hook lua_gethook (lua_State *L) { LUA_API unsigned long lua_gethookmask (lua_State *L) { - return L->hookmask; + return L->hookmask | LUA_MASKCOUNT(L->basehookcount); } diff --git a/ldebug.h b/ldebug.h index e0d0a097..417bd47d 100644 --- a/ldebug.h +++ b/ldebug.h @@ -1,5 +1,5 @@ /* -** $Id: ldebug.h,v 1.30 2002/08/12 17:23:12 roberto Exp roberto $ +** $Id: ldebug.h,v 1.31 2002/08/20 20:03:05 roberto Exp roberto $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ @@ -15,12 +15,10 @@ #define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) -#define resethookcount(L) (L->hookcount = lua_getmaskcount(L->hookmask)) - -#define setallowhook(L,cond) ((L->hookmask) = ((L->hookmask) & ~1) | (cond)) -#define allowhook(L) ((L->hookmask) & 1) +#define resethookcount(L) (L->hookcount = L->basehookcount) +void luaG_inithooks (lua_State *L); void luaG_typeerror (lua_State *L, const TObject *o, const char *opname); void luaG_concaterror (lua_State *L, StkId p1, StkId p2); void luaG_aritherror (lua_State *L, const TObject *p1, const TObject *p2); diff --git a/ldo.c b/ldo.c index ae752ece..176cf0da 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.200 2002/11/13 11:31:39 roberto Exp roberto $ +** $Id: ldo.c,v 1.201 2002/11/14 16:15:53 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -154,7 +154,7 @@ static void luaD_growCI (lua_State *L) { void luaD_callhook (lua_State *L, int event, int line) { lua_Hook hook = L->hook; - if (hook && allowhook(L)) { + if (hook && L->allowhook) { ptrdiff_t top = savestack(L, L->top); ptrdiff_t ci_top = savestack(L, L->ci->top); lua_Debug ar; @@ -163,12 +163,12 @@ void luaD_callhook (lua_State *L, int event, int line) { ar.i_ci = L->ci - L->base_ci; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ L->ci->top = L->top + LUA_MINSTACK; - setallowhook(L, 0); /* cannot call hooks inside a hook */ + L->allowhook = 0; /* cannot call hooks inside a hook */ lua_unlock(L); (*hook)(L, &ar); lua_lock(L); - lua_assert(!allowhook(L)); - setallowhook(L, 1); + lua_assert(!L->allowhook); + L->allowhook = 1; L->ci->top = restorestack(L, ci_top); L->top = restorestack(L, top); } @@ -328,16 +328,16 @@ static void resume (lua_State *L, void *ud) { LUA_API int lua_resume (lua_State *L, int nargs) { int status; - int old_allowhooks; + lu_byte old_allowhooks; lua_lock(L); - old_allowhooks = allowhook(L); + old_allowhooks = L->allowhook; lua_assert(L->errfunc == 0); status = luaD_rawrunprotected(L, resume, &nargs); if (status != 0) { /* error? */ L->ci = L->base_ci; /* go back to initial level */ luaF_close(L, L->ci->base); /* close eventual pending closures */ seterrorobj(L, status, L->ci->base); - setallowhook(L, old_allowhooks); + L->allowhook = old_allowhooks; restore_stack_limit(L); } lua_unlock(L); @@ -383,7 +383,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) { int status; ptrdiff_t old_top = savestack(L, L->top); ptrdiff_t old_ci = saveci(L, L->ci); - int old_allowhooks = allowhook(L); + lu_byte old_allowhooks = L->allowhook; ptrdiff_t old_errfunc = L->errfunc; L->errfunc = errfunc; c.func = L->top - (nargs+1); /* function to be called */ @@ -394,7 +394,7 @@ int luaD_pcall (lua_State *L, int nargs, int nresults, ptrdiff_t errfunc) { luaF_close(L, oldtop); /* close eventual pending closures */ seterrorobj(L, status, oldtop); L->ci = restoreci(L, old_ci); - setallowhook(L, old_allowhooks); + L->allowhook = old_allowhooks; restore_stack_limit(L); } L->errfunc = old_errfunc; diff --git a/lgc.c b/lgc.c index 87ec40c9..15338987 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.157 2002/11/13 11:49:19 roberto Exp roberto $ +** $Id: lgc.c,v 1.158 2002/11/14 11:51:50 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -404,8 +404,8 @@ static void do1gcTM (lua_State *L, Udata *udata) { static void callGCTM (lua_State *L) { - int oldah = allowhook(L); - setallowhook(L, 0); /* stop debug hooks during GC tag methods */ + lu_byte oldah = L->allowhook; + L->allowhook = 0; /* stop debug hooks during GC tag methods */ L->top++; /* reserve space to keep udata while runs its gc method */ while (G(L)->tmudata != NULL) { GCObject *o = G(L)->tmudata; @@ -419,7 +419,7 @@ static void callGCTM (lua_State *L) { do1gcTM(L, udata); } L->top--; - setallowhook(L, oldah); /* restore hooks */ + L->allowhook = oldah; /* restore hooks */ } diff --git a/lstate.c b/lstate.c index 2d19405d..12a771e2 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.110 2002/11/13 11:31:39 roberto Exp roberto $ +** $Id: lstate.c,v 1.111 2002/11/14 16:15:53 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -112,8 +112,9 @@ static void preinit_state (lua_State *L) { L->stacksize = 0; L->errorJmp = NULL; L->hook = NULL; - L->hookmask = 0; - setallowhook(L, 1); + L->hookmask = L->hookinit = 0; + L->basehookcount = 0; + L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->size_ci = 0; diff --git a/lstate.h b/lstate.h index e8bdb32b..6d1deb18 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.100 2002/11/06 19:08:00 roberto Exp roberto $ +** $Id: lstate.h,v 1.101 2002/11/13 11:31:39 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -139,7 +139,10 @@ struct lua_State { CallInfo *end_ci; /* points after end of ci array*/ CallInfo *base_ci; /* array of CallInfo's */ int size_ci; /* size of array `base_ci' */ - unsigned long hookmask; + lu_byte hookmask; + lu_byte allowhook; + lu_byte hookinit; + ls_count basehookcount; ls_count hookcount; lua_Hook hook; TObject _gt; /* table of globals */ diff --git a/lua.h b/lua.h index b36f975c..c3abafa7 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.163 2002/11/07 15:39:23 roberto Exp roberto $ +** $Id: lua.h,v 1.164 2002/11/14 11:51:50 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil ** http://www.lua.org mailto:info@lua.org @@ -327,13 +327,13 @@ LUA_API int lua_pushupvalues (lua_State *L); /* ** Event masks */ -#define LUA_MASKCALL (2 << LUA_HOOKCALL) -#define LUA_MASKRET (2 << LUA_HOOKRET) -#define LUA_MASKLINE (2 << LUA_HOOKLINE) +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) #define LUA_MASKCOUNT(count) ((unsigned long)(count) << 8) #define lua_getmaskcount(mask) ((mask) >> 8) -#define LUA_MAXCOUNT ((1<<24) - 1) +#define LUA_MAXCOUNT ((~(unsigned long)0) >> 8) typedef struct lua_Debug lua_Debug; /* activation record */ diff --git a/lvm.c b/lvm.c index 03ef02fe..e9f122d0 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.260 2002/11/07 15:37:10 roberto Exp roberto $ +** $Id: lvm.c,v 1.261 2002/11/14 16:15:53 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -70,7 +70,7 @@ int luaV_tostring (lua_State *L, StkId obj) { static void traceexec (lua_State *L) { - unsigned long mask = L->hookmask; + lu_byte mask = L->hookmask; if (mask > LUA_MASKLINE) { /* instruction-hook set? */ if (L->hookcount == 0) { luaD_callhook(L, LUA_HOOKCOUNT, -1); @@ -82,6 +82,10 @@ static void traceexec (lua_State *L) { CallInfo *ci = L->ci; Proto *p = ci_func(ci)->l.p; int newline = getline(p, pcRel(*ci->u.l.pc, p)); + if (!L->hookinit) { + luaG_inithooks(L); + return; + } lua_assert(ci->state & CI_HASFRAME); if (pcRel(*ci->u.l.pc, p) == 0) /* tracing may be starting now? */ ci->u.l.savedpc = *ci->u.l.pc; /* initialize `savedpc' */