lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


The current luaL_newmetatable/luaL_checkudata auxiliary functions are
fine but luaL_checkudata adds a significant amount of overhead when
making heavy use of calls that need to check userdata types (which is
very important when creating "safe" APIs).  I have attached a small
extension patch that adds lua_tomuserdata() and luaL_checkmudata() to
the core which gives the application quicker access to the metatable
pointer.   From the developer perspective nothing changes unless they
want to use the new mechanism.

Example usage (simplified):

void *myusertype_meta;

int create_myusertype(lua_State *L) {
  ...
  luaL_newmetatable(L, "myusertype");
  /* cache the metatable pointer locally */
  myusertype_meta = lua_topointer(L, -1);
  ...
}

int some_lua_function(lua_State *L) {
  myusertype *ud = luaL_checkmutype(L, 1, "myusertype", myusertype_meta);
  ...
}

I see about a 30+% increase in general application speed plus the
normal API still works as usual of course.  What do you think?

CR
diff -ru lua-5.1.3.orig/src/lapi.c lua-5.1.3/src/lapi.c
--- lua-5.1.3.orig/src/lapi.c	2008-01-03 10:20:39.000000000 -0500
+++ lua-5.1.3/src/lapi.c	2008-02-28 10:44:13.429884590 -0500
@@ -393,6 +393,18 @@
 }
 
 
+LUA_API void *lua_tomuserdata (lua_State *L, int idx, const void *meta) {
+  StkId o = index2adr(L, idx);
+  switch (ttype(o)) {
+    case LUA_TUSERDATA:
+      if (uvalue(o)->metatable == meta) return (rawuvalue(o) + 1);
+      return NULL;
+    case LUA_TLIGHTUSERDATA: return pvalue(o);
+    default: return NULL;
+  }
+}
+
+
 LUA_API lua_State *lua_tothread (lua_State *L, int idx) {
   StkId o = index2adr(L, idx);
   return (!ttisthread(o)) ? NULL : thvalue(o);
diff -ru lua-5.1.3.orig/src/lauxlib.c lua-5.1.3/src/lauxlib.c
--- lua-5.1.3.orig/src/lauxlib.c	2008-01-21 08:20:51.000000000 -0500
+++ lua-5.1.3/src/lauxlib.c	2008-02-28 10:44:30.923498327 -0500
@@ -137,6 +137,14 @@
 }
 
 
+LUALIB_API void *luaL_checkmudata (lua_State *L, int ud, const char *tname, const void* meta) {
+  void *p = lua_tomuserdata(L, ud, meta);
+  if (p != NULL) return p;
+  luaL_typerror(L, ud, tname);  /* else error */
+  return NULL;  /* to avoid warnings */
+}
+
+
 LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
   if (!lua_checkstack(L, space))
     luaL_error(L, "stack overflow (%s)", mes);