Browse Source

two new fields 'fTransfer'/'nTransfer' in 'lua_Debug' structure
(for information about values being given and returned in function calls)

Roberto Ierusalimschy 7 years ago
parent
commit
422318f677
6 changed files with 52 additions and 19 deletions
  1. 6 2
      ldblib.c
  2. 11 3
      ldebug.c
  3. 22 9
      ldo.c
  4. 3 2
      ldo.h
  5. 7 2
      lstate.h
  6. 3 1
      lua.h

+ 6 - 2
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.150 2015/11/19 19:16:22 roberto Exp roberto $
+** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -146,7 +146,7 @@ static int db_getinfo (lua_State *L) {
   lua_Debug ar;
   int arg;
   lua_State *L1 = getthread(L, &arg);
-  const char *options = luaL_optstring(L, arg+2, "flnStu");
+  const char *options = luaL_optstring(L, arg+2, "flnSrtu");
   checkstack(L, L1, 3);
   if (lua_isfunction(L, arg + 1)) {  /* info about a function? */
     options = lua_pushfstring(L, ">%s", options);  /* add '>' to 'options' */
@@ -180,6 +180,10 @@ static int db_getinfo (lua_State *L) {
     settabss(L, "name", ar.name);
     settabss(L, "namewhat", ar.namewhat);
   }
+  if (strchr(options, 'r')) {
+    settabsi(L, "fTransfer", ar.fTransfer);
+    settabsi(L, "nTransfer", ar.nTransfer);
+  }
   if (strchr(options, 't'))
     settabsb(L, "istailcall", ar.istailcall);
   if (strchr(options, 'L'))

+ 11 - 3
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.153 2018/02/06 19:16:56 roberto Exp roberto $
+** $Id: ldebug.c,v 2.154 2018/02/09 15:16:06 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -356,6 +356,14 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
         }
         break;
       }
+      case 'r': {
+        if (ci == NULL || !(ci->callstatus & CIST_TRAN))
+          ar->fTransfer = ar->nTransfer = 0;
+        else {
+          ar->fTransfer = ci->u2.transferinfo.fTransfer;
+          ar->nTransfer = ci->u2.transferinfo.nTransfer;
+        }
+      }
       case 'L':
       case 'f':  /* handled by lua_getinfo */
         break;
@@ -790,7 +798,7 @@ void luaG_traceexec (lua_State *L) {
   if (!isIT(*(ci->u.l.savedpc - 1)))
     L->top = ci->top;  /* prepare top */
   if (counthook)
-    luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
+    luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0);  /* call count hook */
   if (mask & LUA_MASKLINE) {
     Proto *p = ci_func(ci)->p;
     const Instruction *npc = ci->u.l.savedpc;
@@ -799,7 +807,7 @@ void luaG_traceexec (lua_State *L) {
         npc <= L->oldpc ||  /* when jump back (loop), or when */
         changedline(p, pcRel(L->oldpc, p), npci)) {  /* enter new line */
       int newline = luaG_getfuncline(p, npci);  /* new line */
-      luaD_hook(L, LUA_HOOKLINE, newline);  /* call line hook */
+      luaD_hook(L, LUA_HOOKLINE, newline, 0, 0);  /* call line hook */
     }
     L->oldpc = npc;
   }

+ 22 - 9
ldo.c

@@ -267,9 +267,11 @@ void luaD_inctop (lua_State *L) {
 ** called. (Both 'L->hook' and 'L->hookmask', which triggers this
 ** function, can be changed asynchronously by signals.)
 */
-void luaD_hook (lua_State *L, int event, int line) {
+void luaD_hook (lua_State *L, int event, int line,
+                              int fTransfer, int nTransfer) {
   lua_Hook hook = L->hook;
   if (hook && L->allowhook) {  /* make sure there is a hook */
+    int mask = CIST_HOOKED;
     CallInfo *ci = L->ci;
     ptrdiff_t top = savestack(L, L->top);
     ptrdiff_t ci_top = savestack(L, ci->top);
@@ -277,11 +279,16 @@ void luaD_hook (lua_State *L, int event, int line) {
     ar.event = event;
     ar.currentline = line;
     ar.i_ci = ci;
+    if (nTransfer != 0) {
+      mask |= CIST_TRAN;  /* 'ci' has transfer information */
+      ci->u2.transferinfo.fTransfer = fTransfer;
+      ci->u2.transferinfo.nTransfer = nTransfer;
+    }
     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
     if (L->top + LUA_MINSTACK > ci->top)
       ci->top = L->top + LUA_MINSTACK;
     L->allowhook = 0;  /* cannot call hooks inside a hook */
-    ci->callstatus |= CIST_HOOKED;
+    ci->callstatus |= mask;
     lua_unlock(L);
     (*hook)(L, &ar);
     lua_lock(L);
@@ -289,7 +296,7 @@ void luaD_hook (lua_State *L, int event, int line) {
     L->allowhook = 1;
     ci->top = restorestack(L, ci_top);
     L->top = restorestack(L, top);
-    ci->callstatus &= ~CIST_HOOKED;
+    ci->callstatus &= ~mask;
   }
 }
 
@@ -301,16 +308,18 @@ void luaD_hook (lua_State *L, int event, int line) {
 */
 void luaD_hookcall (lua_State *L, CallInfo *ci) {
   int hook = (ci->callstatus & CIST_TAIL) ? LUA_HOOKTAILCALL : LUA_HOOKCALL;
+  Proto *p;
   if (!(L->hookmask & LUA_MASKCALL))  /* some other hook? */
     return;  /* don't call hook */
+  p = clLvalue(s2v(ci->func))->p;
   L->top = ci->top;  /* prepare top */
   ci->u.l.savedpc++;  /* hooks assume 'pc' is already incremented */
-  luaD_hook(L, hook, -1);
+  luaD_hook(L, hook, -1, 1, p->numparams);
   ci->u.l.savedpc--;  /* correct 'pc' */
 }
 
 
-static void rethook (lua_State *L, CallInfo *ci) {
+static void rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
   int delta = 0;
   if (isLuacode(ci)) {
     Proto *p = clLvalue(s2v(ci->func))->p;
@@ -320,8 +329,10 @@ static void rethook (lua_State *L, CallInfo *ci) {
       L->top = ci->top;  /* correct top */
   }
   if (L->hookmask & LUA_MASKRET) {  /* is return hook on? */
+    int fTransfer;
     ci->func += delta;  /* if vararg, back to virtual 'func' */
-    luaD_hook(L, LUA_HOOKRET, -1);  /* call it */
+    fTransfer = cast(unsigned short, firstres - ci->func);
+    luaD_hook(L, LUA_HOOKRET, -1, fTransfer, nres);  /* call it */
     ci->func -= delta;
   }
   if (isLua(ci->previous))
@@ -396,7 +407,7 @@ static void moveresults (lua_State *L, StkId firstResult, StkId res,
 void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
   if (L->hookmask) {
     ptrdiff_t fr = savestack(L, firstResult);  /* hook may change stack */
-    rethook(L, ci);
+    rethook(L, ci, firstResult, nres);
     firstResult = restorestack(L, fr);
   }
   L->ci = ci->previous;  /* back to caller */
@@ -458,8 +469,10 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
       ci->top = L->top + LUA_MINSTACK;
       ci->func = func;
       lua_assert(ci->top <= L->stack_last);
-      if (L->hookmask & LUA_MASKCALL)
-        luaD_hook(L, LUA_HOOKCALL, -1);
+      if (L->hookmask & LUA_MASKCALL) {
+        int narg = cast_int(L->top - func) - 1;
+        luaD_hook(L, LUA_HOOKCALL, -1, 1, narg);
+      }
       lua_unlock(L);
       n = (*f)(L);  /* do the actual call */
       lua_lock(L);

+ 3 - 2
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.41 2018/02/09 15:16:06 roberto Exp roberto $
+** $Id: ldo.h,v 2.42 2018/02/15 15:34:29 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -52,7 +52,8 @@ typedef void (*Pfunc) (lua_State *L, void *ud);
 
 LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
                                                   const char *mode);
-LUAI_FUNC void luaD_hook (lua_State *L, int event, int line);
+LUAI_FUNC void luaD_hook (lua_State *L, int event, int line,
+                                        int fTransfer, int nTransfer);
 LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci);
 LUAI_FUNC void luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int n);
 LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);

+ 7 - 2
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.154 2018/02/09 15:16:06 roberto Exp roberto $
+** $Id: lstate.h,v 2.155 2018/02/15 18:06:24 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -103,9 +103,13 @@ typedef struct CallInfo {
   union {
     int funcidx;  /* called-function index */
     int nyield;  /* number of values yielded */
+    struct {  /* info about transfered values (for call/return hooks) */
+      unsigned short fTransfer;  /* offset of first value transfered */
+      unsigned short nTransfer;  /* number of values transfered */
+    } transferinfo;
   } u2;
   short nresults;  /* expected number of results from this function */
-  lu_byte callstatus;
+  unsigned short callstatus;
 } CallInfo;
 
 
@@ -120,6 +124,7 @@ typedef struct CallInfo {
 #define CIST_HOOKYIELD	(1<<5)	/* last hook called yielded */
 #define CIST_LEQ	(1<<6)  /* using __lt for __le */
 #define CIST_FIN	(1<<7)  /* call is running a finalizer */
+#define CIST_TRAN	(1<<8)	/* 'ci' has transfer information */
 
 /* active function is a Lua function */
 #define isLua(ci)	(!((ci)->callstatus & CIST_C))

+ 3 - 1
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.337 2017/11/02 11:28:56 roberto Exp $
+** $Id: lua.h,v 1.339 2017/11/07 13:25:26 roberto Exp roberto $
 ** Lua - A Scripting Language
 ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
 ** See Copyright Notice at the end of this file
@@ -452,6 +452,8 @@ struct lua_Debug {
   int lastlinedefined;	/* (S) */
   unsigned char nups;	/* (u) number of upvalues */
   unsigned char nparams;/* (u) number of parameters */
+  unsigned char fTransfer;/* (r) index of first value transfered */
+  unsigned char nTransfer;   /* (r) number of transfered values */
   char isvararg;        /* (u) */
   char istailcall;	/* (t) */
   char short_src[LUA_IDSIZE]; /* (S) */