diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-06-27 08:35:31 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-06-27 08:35:31 -0300 |
commit | b42430fd3a6200eaaf4020be90c4d47f7e251b67 (patch) | |
tree | c47c23ac9d461b79554986769375019dc6dc469c /ldebug.c | |
parent | 60a7492d249860d20098ac2f0b9d863606c38450 (diff) | |
download | lua-b42430fd3a6200eaaf4020be90c4d47f7e251b67.tar.gz lua-b42430fd3a6200eaaf4020be90c4d47f7e251b67.tar.bz2 lua-b42430fd3a6200eaaf4020be90c4d47f7e251b67.zip |
'lineinfo' in prototypes saved as differences instead of absolute
values, so that the array can use bytes instead of ints, reducing
its size. (A new array 'abslineinfo' is used when line differences
do not fit in a byte.)
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? */ |