** 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'
| 934 | ** 'L->top.p' before calling anything that can run the GC. |
| 935 | */ |
| 936 | int luaG_traceexec (lua_State *L, const Instruction *pc) { |
| 937 | CallInfo *ci = L->ci; |
| 938 | lu_byte mask = cast_byte(L->hookmask); |
| 939 | const Proto *p = ci_func(ci)->p; |
| 940 | int counthook; |
| 941 | if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ |
| 942 | ci->u.l.trap = 0; /* don't need to stop again */ |
| 943 | return 0; /* turn off 'trap' */ |
| 944 | } |
| 945 | pc++; /* reference is always next instruction */ |
| 946 | ci->u.l.savedpc = pc; /* save 'pc' */ |
| 947 | counthook = (mask & LUA_MASKCOUNT) && (--L->hookcount == 0); |
| 948 | if (counthook) |
| 949 | resethookcount(L); /* reset count */ |
| 950 | else if (!(mask & LUA_MASKLINE)) |
| 951 | return 1; /* no line hook and count != 0; nothing to be done now */ |
| 952 | if (ci->callstatus & CIST_HOOKYIELD) { /* hook yielded last time? */ |
| 953 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ |
| 954 | return 1; /* do not call hook again (VM yielded, so it did not move) */ |
| 955 | } |
| 956 | if (!luaP_isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ |
| 957 | L->top.p = ci->top.p; /* correct top */ |
| 958 | if (counthook) |
| 959 | luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ |
| 960 | if (mask & LUA_MASKLINE) { |
| 961 | /* 'L->oldpc' may be invalid; use zero in this case */ |
| 962 | int oldpc = (L->oldpc < p->sizecode) ? L->oldpc : 0; |
| 963 | int npci = pcRel(pc, p); |
| 964 | if (npci <= oldpc || /* call hook when jump back (loop), */ |
| 965 | changedline(p, oldpc, npci)) { /* or when enter new line */ |
| 966 | int newline = luaG_getfuncline(p, npci); |
| 967 | luaD_hook(L, LUA_HOOKLINE, newline, 0, 0); /* call line hook */ |
| 968 | } |
| 969 | L->oldpc = npci; /* 'pc' of last call to line hook */ |
| 970 | } |
| 971 | if (L->status == LUA_YIELD) { /* did hook yield? */ |
| 972 | if (counthook) |
| 973 | L->hookcount = 1; /* undo decrement to zero */ |
| 974 | ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ |
| 975 | luaD_throw(L, LUA_YIELD); |
| 976 | } |
| 977 | return 1; /* keep 'trap' on */ |
| 978 | } |
| 979 |
no test coverage detected