lua-users home
lua-l archive

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


I'm making a slight change to the reference mechanism that allows accessing references via pseudo-indexes (simplifies C side), and implements ref and unref operations using direct data structure access (large speed boost).

index2adr is modified to return TValue * inside L->l_gt->l_reference->array
I wanted to ask about potential interference of such references with the garbage collector:
  - Are any barriers needed if index2adr returns pointer to data inside registry array?
  - Which API calls are still safe to do without adding any barriers?

Also, lua_refi and lua_unrefi too much depend on internal table datas, any suggestions to make this patch more upgrade friendly?

--juris

Here is simple implementation. This patch thinks that int is 32 bits.
It assumes nobody else is touching array part of the registry.
New functions are
int lua_refi(L, idx) [-0, +0] 
void lua_unrefi(L, ref) [-0, +0]
Patch starts here:

Index: lauxlib.h
===================================================================
--- lauxlib.h	(revision 20049)
+++ lauxlib.h	(working copy)
@@ -157,10 +157,6 @@
 
 /* compatibility with ref system */
 
-/* pre-defined references */
-#define LUA_NOREF       (-2)
-#define LUA_REFNIL      (-1)
-
 #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
       (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
 
Index: lstate.c
===================================================================
--- lstate.c	(revision 20049)
+++ lstate.c	(working copy)
@@ -164,6 +164,7 @@
   g->strt.nuse = 0;
   g->strt.hash = NULL;
   setnilvalue(registry(L));
+  g->nextrefi = 1;
   luaZ_initbuffer(L, &g->buff);
   g->panic = NULL;
   g->gcstate = GCSpause;
Index: lstate.h
===================================================================
--- lstate.h	(revision 20049)
+++ lstate.h	(working copy)
@@ -87,6 +87,7 @@
   int gcstepmul;  /* GC `granularity' */
   lua_CFunction panic;  /* to be called in unprotected errors */
   TValue l_registry;
+  int nextrefi;
   struct lua_State *mainthread;
   UpVal uvhead;  /* head of double-linked list of all open upvalues */
   struct Table *mt[NUM_TAGS];  /* metatables for basic types */
Index: lapi.c
===================================================================
--- lapi.c	(revision 20049)
+++ lapi.c	(working copy)
@@ -65,13 +65,22 @@
       return &L->env;
     }
     case LUA_GLOBALSINDEX: return gt(L);
-    default: {
+    case LUA_NOREF:
+    case LUA_REFNIL: return cast(TValue *, luaO_nilobject);
+    default: if (idx < LUA_GLOBALSINDEX) {
       Closure *func = curr_func(L);
       idx = LUA_GLOBALSINDEX - idx;
       return (idx <= func->c.nupvalues)
                 ? &func->c.upvalue[idx-1]
                 : cast(TValue *, luaO_nilobject);
     }
+    else {
+      Table *h = hvalue(registry(L));
+      idx = LUA_ENVIRONINDEX - idx;
+      return cast(TValue *, idx > h->sizearray
+	        ? luaO_nilobject
+		: luaH_getnum(h, idx));
+    }
   }
 }
 
@@ -1131,3 +1140,46 @@
   return name;
 }
 
+LUA_API int lua_refi (lua_State *L, int idx) {
+  StkId o;
+  TValue *dst;
+  Table *h;
+  int next;
+  lua_lock(L);
+  h = hvalue(registry(L));
+  next = G(L)->nextrefi;
+  if (next > h->sizearray) {
+    int i = h->sizearray;
+    luaH_resizearray(L, h, h->sizearray < 4 ? 8 : h->sizearray * 2);
+    for (;i < h->sizearray; ++i) {
+      setnvalue(h->array + i, i + 2);
+    }
+  }
+  o = index2adr(L, idx);
+  if (ttisnil(o)) {
+    next = LUA_ENVIRONINDEX - LUA_REFNIL;
+  }
+  else {
+    dst = cast(TValue *, luaH_getnum(h, next));
+    G(L)->nextrefi = nvalue(dst);
+    setobj2t(L, dst, o);
+    luaC_barriert(L, h, o);
+  }
+  lua_unlock(L);
+  return LUA_ENVIRONINDEX - next;
+}
+
+LUA_API void lua_unrefi (lua_State *L, int ref) {
+  TValue *dst;
+  Table *h;
+  lua_lock(L);
+  h = hvalue(registry(L));
+  ref = LUA_ENVIRONINDEX - ref;
+  dst = cast(TValue *, luaH_getnum(h, ref));
+  if (dst != luaO_nilobject) {
+    setnvalue(dst, G(L)->nextrefi);
+    G(L)->nextrefi = ref;
+  }
+  lua_unlock(L);
+}
+
Index: lua.h
===================================================================
--- lua.h	(revision 20049)
+++ lua.h	(working copy)
@@ -35,8 +35,11 @@
 */
 #define LUA_REGISTRYINDEX	(-10000)
 #define LUA_ENVIRONINDEX	(-10001)
-#define LUA_GLOBALSINDEX	(-10002)
+#define LUA_GLOBALSINDEX	(-0x70000000)
 #define lua_upvalueindex(i)	(LUA_GLOBALSINDEX-(i))
+/* pre-defined references */
+#define LUA_NOREF       (INT_MIN + 2)
+#define LUA_REFNIL      (INT_MIN + 1)
 
 
 /* thread status; 0 is OK */
@@ -253,6 +256,8 @@
 LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
 LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
 
+LUA_API int   (lua_refi) (lua_State *L, int idx);
+LUA_API void  (lua_unrefi) (lua_State *L, int ref);
 
 
 /*