mirror of https://github.com/rusefi/lua.git
Optimizations for line hook
The function 'changedline' tries harder to avoid calling 'luaG_getfuncline' plus small changes in the use of 'L->oldpc'.
This commit is contained in:
parent
58aa09a0b9
commit
949187b049
9
lcode.c
9
lcode.c
|
@ -314,15 +314,6 @@ void luaK_patchtohere (FuncState *fs, int list) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** MAXimum number of successive Instructions WiTHout ABSolute line
|
|
||||||
** information.
|
|
||||||
*/
|
|
||||||
#if !defined(MAXIWTHABS)
|
|
||||||
#define MAXIWTHABS 120
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* limit for difference between lines in relative line info. */
|
/* limit for difference between lines in relative line info. */
|
||||||
#define LIMLINEDIFF 0x80
|
#define LIMLINEDIFF 0x80
|
||||||
|
|
||||||
|
|
52
ldebug.c
52
ldebug.c
|
@ -33,8 +33,6 @@
|
||||||
|
|
||||||
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
|
#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
|
||||||
|
|
||||||
/* inverse of 'pcRel' */
|
|
||||||
#define invpcRel(pc, p) ((p)->code + (pc) + 1)
|
|
||||||
|
|
||||||
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
|
||||||
const char **name);
|
const char **name);
|
||||||
|
@ -791,16 +789,30 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Check whether new instruction 'newpc' is in a different line from
|
** Check whether new instruction 'newpc' is in a different line from
|
||||||
** previous instruction 'oldpc'.
|
** previous instruction 'oldpc'. More often than not, 'newpc' is only
|
||||||
|
** one or a few instructions after 'oldpc' (it must be after, see
|
||||||
|
** caller), so try to avoid calling 'luaG_getfuncline'. If they are
|
||||||
|
** too far apart, there is a good chance of a ABSLINEINFO in the way,
|
||||||
|
** so it goes directly to 'luaG_getfuncline'.
|
||||||
*/
|
*/
|
||||||
static int changedline (const Proto *p, int oldpc, int newpc) {
|
static int changedline (const Proto *p, int oldpc, int newpc) {
|
||||||
if (p->lineinfo == NULL) /* no debug information? */
|
if (p->lineinfo == NULL) /* no debug information? */
|
||||||
return 0;
|
return 0;
|
||||||
while (oldpc++ < newpc) {
|
if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */
|
||||||
if (p->lineinfo[oldpc] != 0)
|
int delta = 0; /* line diference */
|
||||||
return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc));
|
int pc = oldpc;
|
||||||
|
for (;;) {
|
||||||
|
int lineinfo = p->lineinfo[++pc];
|
||||||
|
if (lineinfo == ABSLINEINFO)
|
||||||
|
break; /* cannot compute delta; fall through */
|
||||||
|
delta += lineinfo;
|
||||||
|
if (pc == newpc)
|
||||||
|
return (delta != 0); /* delta computed successfully */
|
||||||
}
|
}
|
||||||
return 0; /* no line changes between positions */
|
}
|
||||||
|
/* either instructions are too far apart or there is an absolute line
|
||||||
|
info in the way; compute line difference explicitly */
|
||||||
|
return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -808,20 +820,19 @@ static int changedline (const Proto *p, int oldpc, int newpc) {
|
||||||
** Traces the execution of a Lua function. Called before the execution
|
** Traces the execution of a Lua function. Called before the execution
|
||||||
** of each opcode, when debug is on. 'L->oldpc' stores the last
|
** of each opcode, when debug is on. 'L->oldpc' stores the last
|
||||||
** instruction traced, to detect line changes. When entering a new
|
** instruction traced, to detect line changes. When entering a new
|
||||||
** function, 'npci' will be zero and will test as a new line without
|
** function, 'npci' will be zero and will test as a new line whatever
|
||||||
** the need for 'oldpc'; so, 'oldpc' does not need to be initialized
|
** the value of 'oldpc'. Some exceptional conditions may return to
|
||||||
** before. Some exceptional conditions may return to a function without
|
** a function without setting 'oldpc'. In that case, 'oldpc' may be
|
||||||
** updating 'oldpc'. In that case, 'oldpc' may be invalid; if so, it is
|
** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc'
|
||||||
** reset to zero. (A wrong but valid 'oldpc' at most causes an extra
|
** at most causes an extra call to a line hook.)
|
||||||
** call to a line hook.)
|
** This function is not "Protected" when called, so it should correct
|
||||||
|
** 'L->top' before calling anything that can run the GC.
|
||||||
*/
|
*/
|
||||||
int luaG_traceexec (lua_State *L, const Instruction *pc) {
|
int luaG_traceexec (lua_State *L, const Instruction *pc) {
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
lu_byte mask = L->hookmask;
|
lu_byte mask = L->hookmask;
|
||||||
const Proto *p = ci_func(ci)->p;
|
const Proto *p = ci_func(ci)->p;
|
||||||
int counthook;
|
int counthook;
|
||||||
/* 'L->oldpc' may be invalid; reset it in this case */
|
|
||||||
int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
|
|
||||||
if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
|
if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
|
||||||
ci->u.l.trap = 0; /* don't need to stop again */
|
ci->u.l.trap = 0; /* don't need to stop again */
|
||||||
return 0; /* turn off 'trap' */
|
return 0; /* turn off 'trap' */
|
||||||
|
@ -837,15 +848,16 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
|
||||||
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
|
ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
|
||||||
return 1; /* do not call hook again (VM yielded, so it did not move) */
|
return 1; /* do not call hook again (VM yielded, so it did not move) */
|
||||||
}
|
}
|
||||||
if (!isIT(*(ci->u.l.savedpc - 1)))
|
if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */
|
||||||
L->top = ci->top; /* prepare top */
|
L->top = ci->top; /* correct top */
|
||||||
if (counthook)
|
if (counthook)
|
||||||
luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
|
luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
|
||||||
if (mask & LUA_MASKLINE) {
|
if (mask & LUA_MASKLINE) {
|
||||||
|
/* 'L->oldpc' may be invalid; use zero in this case */
|
||||||
|
int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
|
||||||
int npci = pcRel(pc, p);
|
int npci = pcRel(pc, p);
|
||||||
if (npci == 0 || /* call linehook when enter a new function, */
|
if (npci <= oldpc || /* call hook when jump back (loop), */
|
||||||
pc <= invpcRel(oldpc, p) || /* when jump back (loop), or when */
|
changedline(p, oldpc, npci)) { /* or when enter new line */
|
||||||
changedline(p, oldpc, npci)) { /* enter new line */
|
|
||||||
int newline = luaG_getfuncline(p, npci);
|
int newline = luaG_getfuncline(p, npci);
|
||||||
luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
|
luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
|
||||||
}
|
}
|
||||||
|
|
10
ldebug.h
10
ldebug.h
|
@ -26,6 +26,16 @@
|
||||||
*/
|
*/
|
||||||
#define ABSLINEINFO (-0x80)
|
#define ABSLINEINFO (-0x80)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** MAXimum number of successive Instructions WiTHout ABSolute line
|
||||||
|
** information.
|
||||||
|
*/
|
||||||
|
#if !defined(MAXIWTHABS)
|
||||||
|
#define MAXIWTHABS 120
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
|
LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
|
||||||
LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
|
LUAI_FUNC const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n,
|
||||||
StkId *pos);
|
StkId *pos);
|
||||||
|
|
9
ldo.c
9
ldo.c
|
@ -331,6 +331,7 @@ void luaD_hook (lua_State *L, int event, int line,
|
||||||
** active.
|
** active.
|
||||||
*/
|
*/
|
||||||
void luaD_hookcall (lua_State *L, CallInfo *ci) {
|
void luaD_hookcall (lua_State *L, CallInfo *ci) {
|
||||||
|
L->oldpc = 0; /* set 'oldpc' for new function */
|
||||||
if (L->hookmask & LUA_MASKCALL) { /* is call hook on? */
|
if (L->hookmask & LUA_MASKCALL) { /* is call hook on? */
|
||||||
int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL
|
int event = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL
|
||||||
: LUA_HOOKCALL;
|
: LUA_HOOKCALL;
|
||||||
|
@ -343,9 +344,9 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Executes a call hook for Lua and C functions. This function is called
|
** Executes a return hook for Lua and C functions and sets/corrects
|
||||||
** whenever 'hookmask' is not zero, so it checks whether return hooks are
|
** 'oldpc'. (Note that this correction is needed by the line hook, so it
|
||||||
** active.
|
** is done even when return hooks are off.)
|
||||||
*/
|
*/
|
||||||
static void rethook (lua_State *L, CallInfo *ci, int nres) {
|
static void rethook (lua_State *L, CallInfo *ci, int nres) {
|
||||||
if (L->hookmask & LUA_MASKRET) { /* is return hook on? */
|
if (L->hookmask & LUA_MASKRET) { /* is return hook on? */
|
||||||
|
@ -363,7 +364,7 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) {
|
||||||
ci->func -= delta;
|
ci->func -= delta;
|
||||||
}
|
}
|
||||||
if (isLua(ci = ci->previous))
|
if (isLua(ci = ci->previous))
|
||||||
L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* update 'oldpc' */
|
L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue