aboutsummaryrefslogtreecommitdiff
path: root/ldebug.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldebug.c')
-rw-r--r--ldebug.c92
1 files changed, 85 insertions, 7 deletions
diff --git a/ldebug.c b/ldebug.c
index 4193cda8..6971e475 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.125 2017/05/13 13:04:33 roberto Exp roberto $ 2** $Id: ldebug.c,v 2.126 2017/05/13 13:54:47 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*/
@@ -48,8 +48,61 @@ static int currentpc (CallInfo *ci) {
48} 48}
49 49
50 50
51/*
52** Get a "base line" to find the line corresponding to an instruction.
53** For that, search the array of absolute line info for the largest saved
54** instruction smaller or equal to the wanted instrution. A special
55** case is when there is no absolute info or the instruction is before
56** the first absolute one.
57*/
58static int getbaseline (Proto *f, int pc, int *basepc) {
59 if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
60 *basepc = -1; /* start from the beginning */
61 return f->linedefined;
62 }
63 else {
64 unsigned int i;
65 if (pc >= f->abslineinfo[f->sizeabslineinfo - 1].pc)
66 i = f->sizeabslineinfo - 1; /* instruction is after last saved one */
67 else { /* binary search */
68 unsigned int j = f->sizeabslineinfo - 1; /* pc < anchorlines[j] */
69 i = 0; /* abslineinfo[i] <= pc */
70 while (i < j - 1) {
71 unsigned int m = (j + i) / 2;
72 if (pc >= f->abslineinfo[m].pc)
73 i = m;
74 else
75 j = m;
76 }
77 }
78 *basepc = f->abslineinfo[i].pc;
79 return f->abslineinfo[i].line;
80 }
81}
82
83
84/*
85** Get the line corresponding to instruction 'pc' in function 'f';
86** first gets a base line and from there does the increments until
87** the desired instruction.
88*/
89int luaG_getfuncline (Proto *f, int pc) {
90 if (f->lineinfo == NULL) /* no debug information? */
91 return -1;
92 else {
93 int basepc;
94 int baseline = getbaseline(f, pc, &basepc);
95 while (basepc++ < pc) { /* walk until given instruction */
96 lua_assert(f->lineinfo[basepc] != ABSLINEINFO);
97 baseline += f->lineinfo[basepc]; /* correct line */
98 }
99 return baseline;
100 }
101}
102
103
51static int currentline (CallInfo *ci) { 104static int currentline (CallInfo *ci) {
52 return getfuncline(ci_func(ci)->p, currentpc(ci)); 105 return luaG_getfuncline(ci_func(ci)->p, currentpc(ci));
53} 106}
54 107
55 108
@@ -211,6 +264,14 @@ static void funcinfo (lua_Debug *ar, Closure *cl) {
211} 264}
212 265
213 266
267static int nextline (Proto *p, int currentline, int pc) {
268 if (p->lineinfo[pc] != ABSLINEINFO)
269 return currentline + p->lineinfo[pc];
270 else
271 return luaG_getfuncline(p, pc);
272}
273
274
214static void collectvalidlines (lua_State *L, Closure *f) { 275static void collectvalidlines (lua_State *L, Closure *f) {
215 if (noLuaClosure(f)) { 276 if (noLuaClosure(f)) {
216 setnilvalue(L->top); 277 setnilvalue(L->top);
@@ -219,13 +280,16 @@ static void collectvalidlines (lua_State *L, Closure *f) {
219 else { 280 else {
220 int i; 281 int i;
221 TValue v; 282 TValue v;
222 int *lineinfo = f->l.p->lineinfo; 283 Proto *p = f->l.p;
284 int currentline = p->linedefined;
223 Table *t = luaH_new(L); /* new table to store active lines */ 285 Table *t = luaH_new(L); /* new table to store active lines */
224 sethvalue(L, L->top, t); /* push it on stack */ 286 sethvalue(L, L->top, t); /* push it on stack */
225 api_incr_top(L); 287 api_incr_top(L);
226 setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ 288 setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */
227 for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ 289 for (i = 0; i < p->sizelineinfo; i++) { /* for all lines with code */
228 luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ 290 currentline = nextline(p, currentline, i);
291 luaH_setint(L, t, currentline, &v); /* table[line] = true */
292 }
229 } 293 }
230} 294}
231 295
@@ -681,6 +745,19 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
681} 745}
682 746
683 747
748/*
749** Check whether new instruction 'newpc' is in a different line from
750** previous instruction 'oldpc'.
751*/
752static int changedline (Proto *p, int oldpc, int newpc) {
753 while (oldpc++ < newpc) {
754 if (p->lineinfo[oldpc] != 0)
755 return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc));
756 }
757 return 0; /* no line changes in the way */
758}
759
760
684void luaG_traceexec (lua_State *L) { 761void luaG_traceexec (lua_State *L) {
685 CallInfo *ci = L->ci; 762 CallInfo *ci = L->ci;
686 lu_byte mask = L->hookmask; 763 lu_byte mask = L->hookmask;
@@ -698,11 +775,12 @@ void luaG_traceexec (lua_State *L) {
698 if (mask & LUA_MASKLINE) { 775 if (mask & LUA_MASKLINE) {
699 Proto *p = ci_func(ci)->p; 776 Proto *p = ci_func(ci)->p;
700 int npc = pcRel(ci->u.l.savedpc, p); 777 int npc = pcRel(ci->u.l.savedpc, p);
701 int newline = getfuncline(p, npc);
702 if (npc == 0 || /* call linehook when enter a new function, */ 778 if (npc == 0 || /* call linehook when enter a new function, */
703 ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ 779 ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */
704 newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ 780 changedline(p, pcRel(L->oldpc, p), npc)) { /* enter new line */
781 int newline = luaG_getfuncline(p, npc); /* new line */
705 luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ 782 luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */
783 }
706 } 784 }
707 L->oldpc = ci->u.l.savedpc; 785 L->oldpc = ci->u.l.savedpc;
708 if (L->status == LUA_YIELD) { /* did hook yield? */ 786 if (L->status == LUA_YIELD) { /* did hook yield? */