diff options
author | Li Jin <dragon-fly@qq.com> | 2021-03-03 21:31:01 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2021-03-03 21:33:37 +0800 |
commit | 1df786307c1983b8ce693e3916081a8bcd4e95ae (patch) | |
tree | 6c7aeb2198d825877fd3d179c394b7a5c1f06a17 /src/lua/ldebug.c | |
parent | 66168b112b707172b9035edf8c1daed469781e06 (diff) | |
download | yuescript-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.c | 105 |
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 | ||
39 | static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | 37 | static 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 | */ |
56 | static int getbaseline (const Proto *f, int pc, int *basepc) { | 58 | static 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 | */ |
652 | static int isinstack (CallInfo *ci, const TValue *o) { | 646 | static 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 | */ |
734 | l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { | 731 | l_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 | */ |
796 | static int changedline (const Proto *p, int oldpc, int newpc) { | 797 | static 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 | */ |
818 | int luaG_traceexec (lua_State *L, const Instruction *pc) { | 830 | int 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 | } |