** Traces the execution of a Lua function. Called before the execution ** of each opcode, when debug is on. 'L->oldpc' stores the last ** instruction traced, to detect line changes. When entering a new ** function, 'npci' will be zero and will test as a new line whatever ** the value of 'oldpc'. Some exceptional conditions may return to ** a function without setting 'oldpc'. In that case, 'oldpc'
| 831 | ** 'L->top' before calling anything that can run the GC. |
| 832 | */ |
| 833 | int luaG_traceexec (lua_State *L, const Instruction *pc) { |
| 834 | CallInfo *ci = L->ci; |
| 835 | lu_byte mask = L->hookmask; |
| 836 | const Proto *p = ci_func(ci)->p; |
| 837 | int counthook; |
| 838 | if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ |
| 839 | ci->u.l.trap = 0; /* don't need to stop again */ |
| 840 | return 0; /* turn off 'trap' */ |
| 841 | } |
| 842 | pc++; /* reference is always next instruction */ |
| 843 | ci->u.l.savedpc = pc; /* save 'pc' */ |
| 844 | counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); |
| 845 | if (counthook) |
| 846 | resethookcount(L); /* reset count */ |
| 847 | else if (!(mask & LUA_MASKLINE)) |
| 848 | return 1; /* no line hook and count != 0; nothing to be done now */ |
| 849 | if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ |
| 850 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ |
| 851 | return 1; /* do not call hook again (VM yielded, so it did not move) */ |
| 852 | } |
| 853 | if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ |
| 854 | L->top = ci->top; /* correct top */ |
| 855 | if (counthook) |
| 856 | luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ |
| 857 | if (mask & LUA_MASKLINE) { |
| 858 | /* 'L->oldpc' may be invalid; use zero in this case */ |
| 859 | int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0; |
| 860 | int npci = pcRel(pc, p); |
| 861 | if (npci <= oldpc || /* call hook when jump back (loop), */ |
| 862 | changedline(p, oldpc, npci)) { /* or when enter new line */ |
| 863 | int newline = luaG_getfuncline(p, npci); |
| 864 | luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ |
| 865 | } |
| 866 | L->oldpc = npci; /* 'pc' of last call to line hook */ |
| 867 | } |
| 868 | if (L->status == LUA_YIELD) { /* did hook yield? */ |
| 869 | if (counthook) |
| 870 | L->hookcount = 1; /* undo decrement to zero */ |
| 871 | ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ |
| 872 | ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ |
| 873 | luaD_throw(L, LUA_YIELD); |
| 874 | } |
| 875 | return 1; /* keep 'trap' on */ |
| 876 | } |
| 877 |
no test coverage detected