[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Fast references
- From: "Juris Kalnins" <juris@...>
- Date: Wed, 27 May 2009 14:45:06 +0300
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);
/*