aboutsummaryrefslogtreecommitdiff
path: root/src/lua/ldebug.c
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-03-03 21:31:01 +0800
committerLi Jin <dragon-fly@qq.com>2021-03-03 21:33:37 +0800
commit1df786307c1983b8ce693e3916081a8bcd4e95ae (patch)
tree6c7aeb2198d825877fd3d179c394b7a5c1f06a17 /src/lua/ldebug.c
parent66168b112b707172b9035edf8c1daed469781e06 (diff)
downloadyuescript-1df786307c1983b8ce693e3916081a8bcd4e95ae.tar.gz
yuescript-1df786307c1983b8ce693e3916081a8bcd4e95ae.tar.bz2
yuescript-1df786307c1983b8ce693e3916081a8bcd4e95ae.zip
add new metatable syntax for issue #41, fix reusing local variable issue, update built-in Lua.
Diffstat (limited to 'src/lua/ldebug.c')
-rw-r--r--src/lua/ldebug.c105
1 files changed, 58 insertions, 47 deletions
diff --git a/src/lua/ldebug.c b/src/lua/ldebug.c
index 819550d..8e3657a 100644
--- a/src/lua/ldebug.c
+++ b/src/lua/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);
@@ -48,10 +46,14 @@ static int currentpc (CallInfo *ci) {
48 46
49/* 47/*
50** Get a "base line" to find the line corresponding to an instruction. 48** Get a "base line" to find the line corresponding to an instruction.
51** For that, search the array of absolute line info for the largest saved 49** Base lines are regularly placed at MAXIWTHABS intervals, so usually
52** instruction smaller or equal to the wanted instruction. A special 50** an integer division gets the right place. When the source file has
53** case is when there is no absolute info or the instruction is before 51** large sequences of empty/comment lines, it may need extra entries,
54** the first absolute one. 52** so the original estimate needs a correction.
53** The assertion that the estimate is a lower bound for the correct base
54** is valid as long as the debug info has been generated with the same
55** value for MAXIWTHABS or smaller. (Previous releases use a little
56** smaller value.)
55*/ 57*/
56static int getbaseline (const Proto *f, int pc, int *basepc) { 58static int getbaseline (const Proto *f, int pc, int *basepc) {
57 if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) { 59 if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
@@ -59,20 +61,11 @@ static int getbaseline (const Proto *f, int pc, int *basepc) {
59 return f->linedefined; 61 return f->linedefined;
60 } 62 }
61 else { 63 else {
62 unsigned int i; 64 int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */
63 if (pc >= f->abslineinfo[f->sizeabslineinfo - 1].pc) 65 /* estimate must be a lower bond of the correct base */
64 i = f->sizeabslineinfo - 1; /* instruction is after last saved one */ 66 lua_assert(i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc);
65 else { /* binary search */ 67 while (i + 1 < f->sizeabslineinfo && pc >= f->abslineinfo[i + 1].pc)
66 unsigned int j = f->sizeabslineinfo - 1; /* pc < anchorlines[j] */ 68 i++; /* low estimate; adjust it */
67 i = 0; /* abslineinfo[i] <= pc */
68 while (i < j - 1) {
69 unsigned int m = (j + i) / 2;
70 if (pc >= f->abslineinfo[m].pc)
71 i = m;
72 else
73 j = m;
74 }
75 }
76 *basepc = f->abslineinfo[i].pc; 69 *basepc = f->abslineinfo[i].pc;
77 return f->abslineinfo[i].line; 70 return f->abslineinfo[i].line;
78 } 71 }
@@ -305,8 +298,8 @@ static void collectvalidlines (lua_State *L, Closure *f) {
305 sethvalue2s(L, L->top, t); /* push it on stack */ 298 sethvalue2s(L, L->top, t); /* push it on stack */
306 api_incr_top(L); 299 api_incr_top(L);
307 setbtvalue(&v); /* boolean 'true' to be the value of all indices */ 300 setbtvalue(&v); /* boolean 'true' to be the value of all indices */
308 for (i = 0; i < p->sizelineinfo; i++) { /* for all lines with code */ 301 for (i = 0; i < p->sizelineinfo; i++) { /* for all instructions */
309 currentline = nextline(p, currentline, i); 302 currentline = nextline(p, currentline, i); /* get its line */
310 luaH_setint(L, t, currentline, &v); /* table[line] = true */ 303 luaH_setint(L, t, currentline, &v); /* table[line] = true */
311 } 304 }
312 } 305 }
@@ -645,14 +638,18 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
645 638
646 639
647/* 640/*
648** The subtraction of two potentially unrelated pointers is 641** Check whether pointer 'o' points to some value in the stack
649** not ISO C, but it should not crash a program; the subsequent 642** frame of the current function. Because 'o' may not point to a
650** checks are ISO C and ensure a correct result. 643** value in this stack, we cannot compare it with the region
644** boundaries (undefined behaviour in ISO C).
651*/ 645*/
652static int isinstack (CallInfo *ci, const TValue *o) { 646static int isinstack (CallInfo *ci, const TValue *o) {
653 StkId base = ci->func + 1; 647 StkId pos;
654 ptrdiff_t i = cast(StkId, o) - base; 648 for (pos = ci->func + 1; pos < ci->top; pos++) {
655 return (0 <= i && i < (ci->top - base) && s2v(base + i) == o); 649 if (o == s2v(pos))
650 return 1;
651 }
652 return 0; /* not found */
656} 653}
657 654
658 655
@@ -733,7 +730,7 @@ l_noret luaG_opinterror (lua_State *L, const TValue *p1,
733*/ 730*/
734l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { 731l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) {
735 lua_Integer temp; 732 lua_Integer temp;
736 if (!tointegerns(p1, &temp)) 733 if (!luaV_tointegerns(p1, &temp, LUA_FLOORN2I))
737 p2 = p1; 734 p2 = p1;
738 luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); 735 luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2));
739} 736}
@@ -791,16 +788,30 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) {
791 788
792/* 789/*
793** Check whether new instruction 'newpc' is in a different line from 790** Check whether new instruction 'newpc' is in a different line from
794** previous instruction 'oldpc'. 791** previous instruction 'oldpc'. More often than not, 'newpc' is only
792** one or a few instructions after 'oldpc' (it must be after, see
793** caller), so try to avoid calling 'luaG_getfuncline'. If they are
794** too far apart, there is a good chance of a ABSLINEINFO in the way,
795** so it goes directly to 'luaG_getfuncline'.
795*/ 796*/
796static int changedline (const Proto *p, int oldpc, int newpc) { 797static int changedline (const Proto *p, int oldpc, int newpc) {
797 if (p->lineinfo == NULL) /* no debug information? */ 798 if (p->lineinfo == NULL) /* no debug information? */
798 return 0; 799 return 0;
799 while (oldpc++ < newpc) { 800 if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */
800 if (p->lineinfo[oldpc] != 0) 801 int delta = 0; /* line diference */
801 return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc)); 802 int pc = oldpc;
803 for (;;) {
804 int lineinfo = p->lineinfo[++pc];
805 if (lineinfo == ABSLINEINFO)
806 break; /* cannot compute delta; fall through */
807 delta += lineinfo;
808 if (pc == newpc)
809 return (delta != 0); /* delta computed successfully */
810 }
802 } 811 }
803 return 0; /* no line changes between positions */ 812 /* either instructions are too far apart or there is an absolute line
813 info in the way; compute line difference explicitly */
814 return (luaG_getfuncline(p, oldpc) != luaG_getfuncline(p, newpc));
804} 815}
805 816
806 817
@@ -808,20 +819,19 @@ static int changedline (const Proto *p, int oldpc, int newpc) {
808** Traces the execution of a Lua function. Called before the execution 819** Traces the execution of a Lua function. Called before the execution
809** of each opcode, when debug is on. 'L->oldpc' stores the last 820** of each opcode, when debug is on. 'L->oldpc' stores the last
810** instruction traced, to detect line changes. When entering a new 821** instruction traced, to detect line changes. When entering a new
811** function, 'npci' will be zero and will test as a new line without 822** 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 823** the value of 'oldpc'. Some exceptional conditions may return to
813** before. Some exceptional conditions may return to a function without 824** 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 825** 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 826** at most causes an extra call to a line hook.)
816** call to a line hook.) 827** This function is not "Protected" when called, so it should correct
828** 'L->top' before calling anything that can run the GC.
817*/ 829*/
818int luaG_traceexec (lua_State *L, const Instruction *pc) { 830int luaG_traceexec (lua_State *L, const Instruction *pc) {
819 CallInfo *ci = L->ci; 831 CallInfo *ci = L->ci;
820 lu_byte mask = L->hookmask; 832 lu_byte mask = L->hookmask;
821 const Proto *p = ci_func(ci)->p; 833 const Proto *p = ci_func(ci)->p;
822 int counthook; 834 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? */ 835 if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */
826 ci->u.l.trap = 0; /* don't need to stop again */ 836 ci->u.l.trap = 0; /* don't need to stop again */
827 return 0; /* turn off 'trap' */ 837 return 0; /* turn off 'trap' */
@@ -837,15 +847,16 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) {
837 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ 847 ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */
838 return 1; /* do not call hook again (VM yielded, so it did not move) */ 848 return 1; /* do not call hook again (VM yielded, so it did not move) */
839 } 849 }
840 if (!isIT(*(ci->u.l.savedpc - 1))) 850 if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */
841 L->top = ci->top; /* prepare top */ 851 L->top = ci->top; /* correct top */
842 if (counthook) 852 if (counthook)
843 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ 853 luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */
844 if (mask & LUA_MASKLINE) { 854 if (mask & LUA_MASKLINE) {
855 /* 'L->oldpc' may be invalid; use zero in this case */
856 int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0;
845 int npci = pcRel(pc, p); 857 int npci = pcRel(pc, p);
846 if (npci == 0 || /* call linehook when enter a new function, */ 858 if (npci <= oldpc || /* call hook when jump back (loop), */
847 pc <= invpcRel(oldpc, p) || /* when jump back (loop), or when */ 859 changedline(p, oldpc, npci)) { /* or when enter new line */
848 changedline(p, oldpc, npci)) { /* enter new line */
849 int newline = luaG_getfuncline(p, npci); 860 int newline = luaG_getfuncline(p, npci);
850 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ 861 luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */
851 } 862 }