aboutsummaryrefslogtreecommitdiff
path: root/ldebug.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-01-28 14:40:29 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2021-01-28 14:40:29 -0300
commit949187b049ce329c93d6639b91e244f2b208c807 (patch)
treee758128392692fe349087e457fc743ea4f56e4bb /ldebug.c
parent58aa09a0b91cf81779d6710d7f9d855bb9d3712f (diff)
downloadlua-949187b049ce329c93d6639b91e244f2b208c807.tar.gz
lua-949187b049ce329c93d6639b91e244f2b208c807.tar.bz2
lua-949187b049ce329c93d6639b91e244f2b208c807.zip
Optimizations for line hook
The function 'changedline' tries harder to avoid calling 'luaG_getfuncline' plus small changes in the use of 'L->oldpc'.
Diffstat (limited to 'ldebug.c')
-rw-r--r--ldebug.c52
1 files changed, 32 insertions, 20 deletions
diff --git a/ldebug.c b/ldebug.c
index 819550d7..8dfa18cf 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -33,8 +33,6 @@
33 33
34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL) 34#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_VCCL)
35 35
36/* inverse of 'pcRel' */
37#define invpcRel(pc, p) ((p)->code + (pc) + 1)
38 36
39static const char *funcnamefromcode (lua_State *L, CallInfo *ci, 37static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
40 const char **name); 38 const char **name);
@@ -791,16 +789,30 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
791 789
792/* 790/*
793** Check whether new instruction 'newpc' is in a different line from 791** Check whether new instruction 'newpc' is in a different line from
794** previous instruction 'oldpc'. 792** previous instruction 'oldpc'. More often than not, 'newpc' is only
793** one or a few instructions after 'oldpc' (it must be after, see
794** caller), so try to avoid calling 'luaG_getfuncline'. If they are
795** too far apart, there is a good chance of a ABSLINEINFO in the way,
796** so it goes directly to 'luaG_getfuncline'.
795*/ 797*/
796static int changedline (const Proto *p, int oldpc, int newpc) { 798static int changedline (const Proto *p, int oldpc, int newpc) {
797 if (p->lineinfo == NULL) /* no debug information? */ 799 if (p->lineinfo == NULL) /* no debug information? */
798 return 0; 800 return 0;
799 while (oldpc++ < newpc) { 801 if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */
800 if (p->lineinfo[oldpc] != 0) 802 int delta = 0; /* line diference */
801 return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc)); 803 int pc = oldpc;
804 for (;;) {
805 int lineinfo = p->lineinfo[++pc];
806 if (lineinfo == ABSLINEINFO)
807 break; /* cannot compute delta; fall through */
808 delta += lineinfo;
809 if (pc == newpc)
810 return (delta != 0); /* delta computed successfully */
811 }
802 } 812 }
803 return 0; /* no line changes between positions */ 813 /* either instructions are too far apart or there is an absolute line
814 info in the way; compute line difference explicitly */
815 return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc));
804} 816}
805 817
806 818
@@ -808,20 +820,19 @@ static int changedline (const Proto *p, int oldpc, int newpc) {
808** Traces the execution of a Lua function. Called before the execution 820** Traces the execution of a Lua function. Called before the execution
809** of each opcode, when debug is on. 'L->oldpc' stores the last 821** of each opcode, when debug is on. 'L->oldpc' stores the last
810** instruction traced, to detect line changes. When entering a new 822** instruction traced, to detect line changes. When entering a new
811** function, 'npci' will be zero and will test as a new line without 823** function, 'npci' will be zero and will test as a new line whatever
812** the need for 'oldpc'; so, 'oldpc' does not need to be initialized 824** the value of 'oldpc'. Some exceptional conditions may return to
813** before. Some exceptional conditions may return to a function without 825** a function without setting 'oldpc'. In that case, 'oldpc' may be
814** updating 'oldpc'. In that case, 'oldpc' may be invalid; if so, it is 826** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc'
815** reset to zero. (A wrong but valid 'oldpc' at most causes an extra 827** at most causes an extra call to a line hook.)
816** call to a line hook.) 828** This function is not "Protected" when called, so it should correct
829** 'L->top' before calling anything that can run the GC.
817*/ 830*/
818int luaG_traceexec (lua_State *L, const Instruction *pc) { 831int luaG_traceexec (lua_State *L, const Instruction *pc) {
819 CallInfo *ci = L->ci; 832 CallInfo *ci = L->ci;
820 lu_byte mask = L->hookmask; 833 lu_byte mask = L->hookmask;
821 const Proto *p = ci_func(ci)->p; 834 const Proto *p = ci_func(ci)->p;
822 int counthook; 835 int counthook;
823 /* 'L->oldpc' may be invalid; reset it in this case */
824 int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
825 if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ 836 if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
826 ci->u.l.trap = 0; /* don't need to stop again */ 837 ci->u.l.trap = 0; /* don't need to stop again */
827 return 0; /* turn off 'trap' */ 838 return 0; /* turn off 'trap' */
@@ -837,15 +848,16 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
837 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ 848 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
838 return 1; /* do not call hook again (VM yielded, so it did not move) */ 849 return 1; /* do not call hook again (VM yielded, so it did not move) */
839 } 850 }
840 if (!isIT(*(ci->u.l.savedpc - 1))) 851 if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */
841 L->top = ci->top; /* prepare top */ 852 L->top = ci->top; /* correct top */
842 if (counthook) 853 if (counthook)
843 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ 854 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
844 if (mask & LUA_MASKLINE) { 855 if (mask & LUA_MASKLINE) {
856 /* 'L->oldpc' may be invalid; use zero in this case */
857 int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
845 int npci = pcRel(pc, p); 858 int npci = pcRel(pc, p);
846 if (npci == 0 || /* call linehook when enter a new function, */ 859 if (npci <= oldpc || /* call hook when jump back (loop), */
847 pc <= invpcRel(oldpc, p) || /* when jump back (loop), or when */ 860 changedline(p, oldpc, npci)) { /* or when enter new line */
848 changedline(p, oldpc, npci)) { /* enter new line */
849 int newline = luaG_getfuncline(p, npci); 861 int newline = luaG_getfuncline(p, npci);
850 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ 862 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
851 } 863 }