about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik K. Agaram <vc@akkartik.com>2022-03-16 23:51:23 -0700
committerKartik K. Agaram <vc@akkartik.com>2022-03-16 23:53:08 -0700
commit5380817ce63e1c830646a04edffb4b49aa16342e (patch)
tree1d94063a60360280b19a54c9563fc3b1da184767
parent76d1dda2402d24f5f43387d13773b3c2d03e180b (diff)
downloadteliva-5380817ce63e1c830646a04edffb4b49aa16342e.tar.gz
function names from globals rather than debug info
This reclaims all the slowdown in sieve.tlv, and it also is now smart
enough to detect calls to global bindings that pass through variables.

On the flip side, we lose names for non-globals. But that's not very
useful anyway in Teliva's context.

This is still not enough to detect callers through coroutines
(intervening anonymous functions), though.
-rw-r--r--src/teliva.c44
1 files changed, 22 insertions, 22 deletions
diff --git a/src/teliva.c b/src/teliva.c
index c85e823..b0e6a56 100644
--- a/src/teliva.c
+++ b/src/teliva.c
@@ -309,33 +309,32 @@ static const char* name_of_global(lua_State* L, const CallInfo* ci, int frame) {
   int gt = lua_gettop(L);
   lua_pushinteger(L, func);
   lua_rawget(L, gt);
-  if (lua_isnil(L, -1)) {
-    // set value if it doesn't exist yet
-    lua_Debug f;
-    lua_getstack(L, frame, &f);
-    lua_getinfo(L, "n", &f);
-    lua_pushinteger(L, func);
-    if (f.name) {
-      result = strdup(f.name);
-      lua_pushstring(L, result);
-    }
-    else {
-      lua_pushinteger(L, 0);
-    }
-    lua_rawset(L, gt);
-  }
-  else if (lua_isnumber(L, -1)) {
-    // return null
-  }
-  else {
-    result = lua_tostring(L, -1);
-  }
+  if (!lua_isnil(L, -1))
+    result = lua_tostring(L, -1);  // safe because global names are long-lived and never GC'd
   lua_pop(L, 1);  // value
-  lua_pop(L, 1);  // table of function names
+  lua_pop(L, 1);  // table of global names
   assert(lua_gettop(L) == oldtop);
   return result;
 }
 
+static void precompute_names_of_globals(lua_State* L) {
+  int oldtop = lua_gettop(L);
+  luaL_newmetatable(L, "__teliva_global_name");
+  int gt = lua_gettop(L);
+  lua_pushvalue(L, LUA_GLOBALSINDEX);
+  int table = lua_gettop(L);
+  for (lua_pushnil(L); lua_next(L, table) != 0; lua_pop(L, 1)) {
+    const char* key = lua_tostring(L, -2);
+    const char* value = lua_topointer(L, -1);
+    lua_pushinteger(L, value);
+    lua_pushstring(L, key);
+    lua_rawset(L, gt);
+  }
+  lua_pop(L, 1);  // table of globals
+  lua_pop(L, 1);  // table of global names
+  assert(lua_gettop(L) == oldtop);
+}
+
 static void save_caller(lua_State* L, const char* name, const char* caller_name) {
   int oldtop = lua_gettop(L);
   // push table of caller tables
@@ -1802,6 +1801,7 @@ int load_image(lua_State* L, char** argv, int n) {
 //?   exit(1);
   status = load_definitions(L);
   if (status != 0) return 0;
+  precompute_names_of_globals(L);
   /* run tests */
   status = run_tests(L);
   if (status != 0) return report_in_developer_mode(L, status);