diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-12-14 12:50:05 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2021-12-14 12:50:05 -0300 |
| commit | 066e0f93c4901e601d93e31fb700f8f66f95feb8 (patch) | |
| tree | 8b7464bbc4bbe12db97eb34f3b28874caffd1411 | |
| parent | 0bfc572e51d9035a615ef6e9523f736c9ffa8e57 (diff) | |
| download | lua-066e0f93c4901e601d93e31fb700f8f66f95feb8.tar.gz lua-066e0f93c4901e601d93e31fb700f8f66f95feb8.tar.bz2 lua-066e0f93c4901e601d93e31fb700f8f66f95feb8.zip | |
Fix debug information about finalizers
The flag CIST_FIN does not mark a finalizer, but the function that was
running when the finalizer was called. (So, the function did not call
the finalizer, but it looks that way in the stack.)
| -rw-r--r-- | ldebug.c | 54 | ||||
| -rw-r--r-- | lgc.c | 2 | ||||
| -rw-r--r-- | lstate.h | 2 | ||||
| -rw-r--r-- | testes/db.lua | 2 | ||||
| -rw-r--r-- | testes/gc.lua | 2 |
5 files changed, 35 insertions, 27 deletions
| @@ -34,8 +34,8 @@ | |||
| 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 | 36 | ||
| 37 | static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | 37 | static const char *funcnamefromcall (lua_State *L, CallInfo *ci, |
| 38 | const char **name); | 38 | const char **name); |
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | static int currentpc (CallInfo *ci) { | 41 | static int currentpc (CallInfo *ci) { |
| @@ -317,15 +317,9 @@ static void collectvalidlines (lua_State *L, Closure *f) { | |||
| 317 | 317 | ||
| 318 | 318 | ||
| 319 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | 319 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { |
| 320 | if (ci == NULL) /* no 'ci'? */ | 320 | /* calling function is a known function? */ |
| 321 | return NULL; /* no info */ | 321 | if (ci != NULL && !(ci->callstatus & CIST_TAIL)) |
| 322 | else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ | 322 | return funcnamefromcall(L, ci->previous, name); |
| 323 | *name = "__gc"; | ||
| 324 | return "metamethod"; /* report it as such */ | ||
| 325 | } | ||
| 326 | /* calling function is a known Lua function? */ | ||
| 327 | else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) | ||
| 328 | return funcnamefromcode(L, ci->previous, name); | ||
| 329 | else return NULL; /* no way to find a name */ | 323 | else return NULL; /* no way to find a name */ |
| 330 | } | 324 | } |
| 331 | 325 | ||
| @@ -597,16 +591,10 @@ static const char *getobjname (const Proto *p, int lastpc, int reg, | |||
| 597 | ** Returns what the name is (e.g., "for iterator", "method", | 591 | ** Returns what the name is (e.g., "for iterator", "method", |
| 598 | ** "metamethod") and sets '*name' to point to the name. | 592 | ** "metamethod") and sets '*name' to point to the name. |
| 599 | */ | 593 | */ |
| 600 | static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | 594 | static const char *funcnamefromcode (lua_State *L, const Proto *p, |
| 601 | const char **name) { | 595 | int pc, const char **name) { |
| 602 | TMS tm = (TMS)0; /* (initial value avoids warnings) */ | 596 | TMS tm = (TMS)0; /* (initial value avoids warnings) */ |
| 603 | const Proto *p = ci_func(ci)->p; /* calling function */ | ||
| 604 | int pc = currentpc(ci); /* calling instruction index */ | ||
| 605 | Instruction i = p->code[pc]; /* calling instruction */ | 597 | Instruction i = p->code[pc]; /* calling instruction */ |
| 606 | if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ | ||
| 607 | *name = "?"; | ||
| 608 | return "hook"; | ||
| 609 | } | ||
| 610 | switch (GET_OPCODE(i)) { | 598 | switch (GET_OPCODE(i)) { |
| 611 | case OP_CALL: | 599 | case OP_CALL: |
| 612 | case OP_TAILCALL: | 600 | case OP_TAILCALL: |
| @@ -643,6 +631,26 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | |||
| 643 | return "metamethod"; | 631 | return "metamethod"; |
| 644 | } | 632 | } |
| 645 | 633 | ||
| 634 | |||
| 635 | /* | ||
| 636 | ** Try to find a name for a function based on how it was called. | ||
| 637 | */ | ||
| 638 | static const char *funcnamefromcall (lua_State *L, CallInfo *ci, | ||
| 639 | const char **name) { | ||
| 640 | if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ | ||
| 641 | *name = "?"; | ||
| 642 | return "hook"; | ||
| 643 | } | ||
| 644 | else if (ci->callstatus & CIST_FIN) { /* was it called as a finalizer? */ | ||
| 645 | *name = "__gc"; | ||
| 646 | return "metamethod"; /* report it as such */ | ||
| 647 | } | ||
| 648 | else if (isLua(ci)) | ||
| 649 | return funcnamefromcode(L, ci_func(ci)->p, currentpc(ci), name); | ||
| 650 | else | ||
| 651 | return NULL; | ||
| 652 | } | ||
| 653 | |||
| 646 | /* }====================================================== */ | 654 | /* }====================================================== */ |
| 647 | 655 | ||
| 648 | 656 | ||
| @@ -728,14 +736,14 @@ l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { | |||
| 728 | 736 | ||
| 729 | 737 | ||
| 730 | /* | 738 | /* |
| 731 | ** Raise an error for calling a non-callable object. Try to find | 739 | ** Raise an error for calling a non-callable object. Try to find a name |
| 732 | ** a name for the object based on the code that made the call | 740 | ** for the object based on how it was called ('funcnamefromcall'); if it |
| 733 | ** ('funcnamefromcode'); if it cannot get a name there, try 'varinfo'. | 741 | ** cannot get a name there, try 'varinfo'. |
| 734 | */ | 742 | */ |
| 735 | l_noret luaG_callerror (lua_State *L, const TValue *o) { | 743 | l_noret luaG_callerror (lua_State *L, const TValue *o) { |
| 736 | CallInfo *ci = L->ci; | 744 | CallInfo *ci = L->ci; |
| 737 | const char *name = NULL; /* to avoid warnings */ | 745 | const char *name = NULL; /* to avoid warnings */ |
| 738 | const char *kind = (isLua(ci)) ? funcnamefromcode(L, ci, &name) : NULL; | 746 | const char *kind = funcnamefromcall(L, ci, &name); |
| 739 | const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o); | 747 | const char *extra = kind ? formatvarinfo(L, kind, name) : varinfo(L, o); |
| 740 | typeerror(L, o, "call", extra); | 748 | typeerror(L, o, "call", extra); |
| 741 | } | 749 | } |
| @@ -917,7 +917,7 @@ static void GCTM (lua_State *L) { | |||
| 917 | L->allowhook = oldah; /* restore hooks */ | 917 | L->allowhook = oldah; /* restore hooks */ |
| 918 | g->gcstp = oldgcstp; /* restore state */ | 918 | g->gcstp = oldgcstp; /* restore state */ |
| 919 | if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ | 919 | if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ |
| 920 | luaE_warnerror(L, "__gc metamethod"); | 920 | luaE_warnerror(L, "__gc"); |
| 921 | L->top--; /* pops error object */ | 921 | L->top--; /* pops error object */ |
| 922 | } | 922 | } |
| 923 | } | 923 | } |
| @@ -209,7 +209,7 @@ typedef struct CallInfo { | |||
| 209 | #define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ | 209 | #define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ |
| 210 | #define CIST_TAIL (1<<5) /* call was tail called */ | 210 | #define CIST_TAIL (1<<5) /* call was tail called */ |
| 211 | #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ | 211 | #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ |
| 212 | #define CIST_FIN (1<<7) /* call is running a finalizer */ | 212 | #define CIST_FIN (1<<7) /* function "called" a finalizer */ |
| 213 | #define CIST_TRAN (1<<8) /* 'ci' has transfer information */ | 213 | #define CIST_TRAN (1<<8) /* 'ci' has transfer information */ |
| 214 | #define CIST_CLSRET (1<<9) /* function is closing tbc variables */ | 214 | #define CIST_CLSRET (1<<9) /* function is closing tbc variables */ |
| 215 | /* Bits 10-12 are used for CIST_RECST (see below) */ | 215 | /* Bits 10-12 are used for CIST_RECST (see below) */ |
diff --git a/testes/db.lua b/testes/db.lua index e0699724..f891e9b8 100644 --- a/testes/db.lua +++ b/testes/db.lua | |||
| @@ -887,7 +887,7 @@ do -- testing debug info for finalizers | |||
| 887 | 887 | ||
| 888 | -- create a piece of garbage with a finalizer | 888 | -- create a piece of garbage with a finalizer |
| 889 | setmetatable({}, {__gc = function () | 889 | setmetatable({}, {__gc = function () |
| 890 | local t = debug.getinfo(2) -- get callee information | 890 | local t = debug.getinfo(1) -- get function information |
| 891 | assert(t.namewhat == "metamethod") | 891 | assert(t.namewhat == "metamethod") |
| 892 | name = t.name | 892 | name = t.name |
| 893 | end}) | 893 | end}) |
diff --git a/testes/gc.lua b/testes/gc.lua index d865cb28..381c5548 100644 --- a/testes/gc.lua +++ b/testes/gc.lua | |||
| @@ -371,7 +371,7 @@ if T then | |||
| 371 | 371 | ||
| 372 | warn("@on"); warn("@store") | 372 | warn("@on"); warn("@store") |
| 373 | collectgarbage() | 373 | collectgarbage() |
| 374 | assert(string.find(_WARN, "error in __gc metamethod")) | 374 | assert(string.find(_WARN, "error in __gc")) |
| 375 | assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = false | 375 | assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = false |
| 376 | for i = 8, 10 do assert(s[i]) end | 376 | for i = 8, 10 do assert(s[i]) end |
| 377 | 377 | ||
