diff options
Diffstat (limited to 'ldebug.c')
-rw-r--r-- | ldebug.c | 92 |
1 files changed, 85 insertions, 7 deletions
@@ -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 | */ | ||
58 | static 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 | */ | ||
89 | int 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 | |||
51 | static int currentline (CallInfo *ci) { | 104 | static 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 | ||
267 | static 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 | |||
214 | static void collectvalidlines (lua_State *L, Closure *f) { | 275 | static 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 | */ | ||
752 | static 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 | |||
684 | void luaG_traceexec (lua_State *L) { | 761 | void 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? */ |