lua-users home
lua-l archive

Fast references

[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);
 
 
 /* 

AltStyle によって変換されたページ (->オリジナル) /