From beee01b170c5fea9ed4527b28b9221d2df1baaba Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy <roberto@inf.puc-rio.br> Date: Tue, 17 Apr 2001 14:35:54 -0300 Subject: re-implementation of refs through weak tables --- lapi.c | 76 +++++++++++++++++++++++++++++++++++++++------------------------- lgc.c | 35 +++--------------------------- lstate.c | 25 ++++----------------- lstate.h | 22 +++---------------- ltests.c | 15 ++++++++++--- lua.h | 25 +++++++++++---------- 6 files changed, 81 insertions(+), 117 deletions(-) diff --git a/lapi.c b/lapi.c index 243087fe..c715301d 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.138 2001/04/11 14:42:41 roberto Exp roberto $ +** $Id: lapi.c,v 1.139 2001/04/11 18:39:37 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -417,21 +417,18 @@ LUA_API void lua_getglobals (lua_State *L) { LUA_API int lua_getref (lua_State *L, int ref) { - int status = 1; + int status; lua_lock(L); if (ref == LUA_REFNIL) { setnilvalue(L->top); - api_incr_top(L); + status = 1; } else { - api_check(L, 0 <= ref && ref < G(L)->nref); - if (G(L)->refArray[ref].st != LOCK && G(L)->refArray[ref].st != HOLD) - status = 0; - else { - setobj(L->top, &G(L)->refArray[ref].o); - api_incr_top(L); - } + setobj(L->top, luaH_getnum(G(L)->weakregistry, ref)); + status = (ttype(L->top) != LUA_TNIL); } + if (status) + api_incr_top(L); lua_unlock(L); return status; } @@ -445,6 +442,22 @@ LUA_API void lua_newtable (lua_State *L) { } +LUA_API void lua_getregistry (lua_State *L) { + lua_lock(L); + sethvalue(L->top, G(L)->registry); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_getweakregistry (lua_State *L) { + lua_lock(L); + sethvalue(L->top, G(L)->weakregistry); + api_incr_top(L); + lua_unlock(L); +} + + /* ** set functions (stack -> Lua) @@ -508,25 +521,26 @@ LUA_API void lua_setglobals (lua_State *L) { LUA_API int lua_ref (lua_State *L, int lock) { int ref; - lua_lock(L); - api_checknelems(L, 1); - if (ttype(L->top-1) == LUA_TNIL) + if (lua_isnil(L, -1)) { + lua_pop(L, 1); ref = LUA_REFNIL; + } else { - if (G(L)->refFree != NONEXT) { /* is there a free place? */ - ref = G(L)->refFree; - G(L)->refFree = G(L)->refArray[ref].st; - } - else { /* no more free places */ - luaM_growvector(L, G(L)->refArray, G(L)->nref, G(L)->sizeref, struct Ref, - MAX_INT, l_s("reference table overflow")); - ref = G(L)->nref++; + lua_getweakregistry(L); + ref = lua_getn(L, -1) + 1; + lua_pushvalue(L, -2); + lua_rawseti(L, -2, ref); + if (lock) { + lua_getregistry(L); + lua_pushvalue(L, -3); + lua_rawseti(L, -2, ref); + lua_pop(L, 1); /* remove registry */ } - setobj(&G(L)->refArray[ref].o, L->top-1); - G(L)->refArray[ref].st = lock ? LOCK : HOLD; + lua_pushliteral(L, "n"); + lua_pushnumber(L, ref); + lua_settable(L, -3); + lua_pop(L, 2); } - L->top--; - lua_unlock(L); return ref; } @@ -671,13 +685,15 @@ LUA_API void lua_error (lua_State *L, const l_char *s) { LUA_API void lua_unref (lua_State *L, int ref) { - lua_lock(L); if (ref >= 0) { - api_check(L, ref < G(L)->nref && G(L)->refArray[ref].st < 0); - G(L)->refArray[ref].st = G(L)->refFree; - G(L)->refFree = ref; + lua_getregistry(L); + lua_pushnil(L); + lua_rawseti(L, -2, ref); + lua_getweakregistry(L); + lua_pushnil(L); + lua_rawseti(L, -2, ref); + lua_pop(L, 2); /* remove both registries */ } - lua_unlock(L); } diff --git a/lgc.c b/lgc.c index a7f96f8c..0237b88c 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.95 2001/03/26 14:31:49 roberto Exp roberto $ +** $Id: lgc.c,v 1.96 2001/04/11 14:42:41 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -111,15 +111,6 @@ static void markstacks (lua_State *L, GCState *st) { } -static void marklock (global_State *G, GCState *st) { - int i; - for (i=0; i<G->nref; i++) { - if (G->refArray[i].st == LOCK) - markobject(st, &G->refArray[i].o); - } -} - - static void marktagmethods (global_State *G, GCState *st) { int t; for (t=0; t<G->ntag; t++) { @@ -176,8 +167,9 @@ static void markall (lua_State *L) { st.tmark = NULL; marktagmethods(G(L), &st); /* mark tag methods */ markstacks(L, &st); /* mark all stacks */ - marklock(G(L), &st); /* mark locked objects */ marktable(&st, G(L)->type2tag); + marktable(&st, G(L)->registry); + marktable(&st, G(L)->weakregistry); for (;;) { /* mark tables and closures */ if (st.cmark) { Closure *f = st.cmark; /* get first closure from list */ @@ -208,26 +200,6 @@ static int hasmark (const TObject *o) { } -/* macro for internal debugging; check if a link of free refs is valid */ -#define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n)) - -static void invalidaterefs (global_State *G) { - int n = G->nref; - int i; - for (i=0; i<n; i++) { - struct Ref *r = &G->refArray[i]; - if (r->st == HOLD && !hasmark(&r->o)) - r->st = COLLECTED; - lua_assert((r->st == LOCK && hasmark(&r->o)) || - (r->st == HOLD && hasmark(&r->o)) || - r->st == COLLECTED || - r->st == NONEXT || - (r->st < n && VALIDLINK(L, G->refArray[r->st].st, n))); - } - lua_assert(VALIDLINK(L, G->refFree, n)); -} - - static void invalidatetable (Hash *h) { int i; for (i=0; i<h->size; i++) { @@ -408,7 +380,6 @@ void luaC_collect (lua_State *L, int all) { void luaC_collectgarbage (lua_State *L) { markall(L); - invalidaterefs(G(L)); /* check unlocked references */ invalidatetables(G(L)); luaC_collect(L, 0); checkMbuffer(L); diff --git a/lstate.c b/lstate.c index 1006dbec..63e15283 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 1.60 2001/03/09 18:05:05 roberto Exp roberto $ +** $Id: lstate.c,v 1.61 2001/03/26 14:31:49 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -29,20 +29,6 @@ struct Sopen { static void close_state (lua_State *L, lua_State *OL); -/* -** initialize ref array and registry -*/ -#define INIT_REFSIZE 4 - -static void ref_init (lua_State *L) { - G(L)->refArray = luaM_newvector(L, INIT_REFSIZE, struct Ref); - G(L)->sizeref = INIT_REFSIZE; - sethvalue(&G(L)->refArray[0].o, luaH_new(L, 0)); - G(L)->refArray[0].st = LOCK; - G(L)->nref = 1; -} - - /* ** open parts that may cause memory-allocation errors */ @@ -74,18 +60,16 @@ static void f_luaopen (lua_State *L, void *ud) { G(L)->TMtable = NULL; G(L)->sizeTM = 0; G(L)->ntag = 0; - G(L)->refArray = NULL; - G(L)->nref = 0; - G(L)->sizeref = 0; - G(L)->refFree = NONEXT; G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); luaD_init(L, so->stacksize); /* init stack */ L->gt = luaH_new(L, 10); /* table of globals */ G(L)->type2tag = luaH_new(L, 10); + G(L)->registry = luaH_new(L, 0); + G(L)->weakregistry = luaH_new(L, 0); + G(L)->weakregistry->weakmode = LUA_WEAK_VALUE; /* make weakregistry weak */ luaS_init(L); luaX_init(L); luaT_init(L); - ref_init(L); G(L)->GCthreshold = 4*G(L)->nblocks; } } @@ -133,7 +117,6 @@ static void close_state (lua_State *L, lua_State *OL) { lua_assert(G(L)->roottable == NULL); luaS_freeall(L); luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); - luaM_freearray(L, G(L)->refArray, G(L)->sizeref, struct Ref); luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char); luaM_freelem(NULL, L->G, global_State); } diff --git a/lstate.h b/lstate.h index 69fd02ad..7c0e808d 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 1.54 2001/03/02 17:27:50 roberto Exp roberto $ +** $Id: lstate.h,v 1.55 2001/03/07 18:09:25 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -32,20 +32,6 @@ #endif -/* -** marks for Reference array -*/ -#define NONEXT -1 /* to end the free list */ -#define HOLD -2 -#define COLLECTED -3 -#define LOCK -4 - - -struct Ref { - TObject o; - int st; /* can be LOCK, HOLD, COLLECTED, or next (for free list) */ -}; - struct lua_longjmp; /* defined in ldo.c */ struct TM; /* defined in ltm.h */ @@ -70,13 +56,11 @@ typedef struct global_State { stringtable strt; /* hash table for strings */ stringtable udt; /* hash table for udata */ Hash *type2tag; /* hash table from type names to tags */ + Hash *registry; /* (strong) registry table */ + Hash *weakregistry; /* weakregistry table */ struct TM *TMtable; /* table for tag methods */ int sizeTM; /* size of TMtable */ int ntag; /* number of tags in TMtable */ - struct Ref *refArray; /* locked objects */ - int nref; /* first unused element in refArray */ - int sizeref; /* size of refArray */ - int refFree; /* list of free positions in refArray */ lu_mem GCthreshold; lu_mem nblocks; /* number of `bytes' currently allocated */ } global_State; diff --git a/ltests.c b/ltests.c index d012df8b..d761d065 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 1.77 2001/03/26 14:31:49 roberto Exp roberto $ +** $Id: ltests.c,v 1.78 2001/04/11 14:42:41 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -383,21 +383,30 @@ static int string_query (lua_State *L) { static int tref (lua_State *L) { + int level = lua_gettop(L); luaL_checkany(L, 1); lua_pushvalue(L, 1); lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1))); + assert(lua_gettop(L) == level+1); /* +1 for result */ return 1; } static int getref (lua_State *L) { - if (lua_getref(L, luaL_check_int(L, 1))) + int level = lua_gettop(L); + if (lua_getref(L, luaL_check_int(L, 1))) { + assert(lua_gettop(L) == level+1); return 1; - else + } + else { + assert(lua_gettop(L) == level); return 0; + } } static int unref (lua_State *L) { + int level = lua_gettop(L); lua_unref(L, luaL_check_int(L, 1)); + assert(lua_gettop(L) == level); return 0; } diff --git a/lua.h b/lua.h index 313a32be..4bfbc336 100644 --- a/lua.h +++ b/lua.h @@ -1,8 +1,8 @@ /* -** $Id: lua.h,v 1.94 2001/04/11 14:42:41 roberto Exp roberto $ +** $Id: lua.h,v 1.95 2001/04/11 18:39:37 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil -** e-mail: lua@tecgraf.puc-rio.br +** e-mail: info@lua.org ** www: http://www.lua.org ** See Copyright Notice at the end of this file */ @@ -29,24 +29,20 @@ /* pre-defined references */ #define LUA_NOREF (-2) #define LUA_REFNIL (-1) -#define LUA_REFREGISTRY 0 - -/* pre-defined tags */ -#define LUA_NOTAG (-2) -/* option for multiple returns in lua_call */ +/* option for multiple returns in `lua_call' */ #define LUA_MULTRET (-1) -/* error codes for lua_do* */ +/* error codes for `lua_do*' and the like */ #define LUA_ERRRUN 1 #define LUA_ERRFILE 2 #define LUA_ERRSYNTAX 3 #define LUA_ERRMEM 4 #define LUA_ERRERR 5 -/* weak modes */ +/* weak-table modes */ #define LUA_WEAK_KEY 1 #define LUA_WEAK_VALUE 2 @@ -67,6 +63,11 @@ typedef int (*lua_CFunction) (lua_State *L); #define LUA_TTABLE 4 #define LUA_TFUNCTION 5 +/* +** an invalid `tag' +*/ +#define LUA_NOTAG (-2) + /* @@ -77,7 +78,7 @@ typedef int (*lua_CFunction) (lua_State *L); #endif -/* minimum stack available for a C function */ +/* minimum Lua stack available to a C function */ #define LUA_MINSTACK 20 @@ -163,6 +164,8 @@ LUA_API void lua_getglobals (lua_State *L); LUA_API void lua_gettagmethod (lua_State *L, int tag, const lua_char *event); LUA_API int lua_getref (lua_State *L, int ref); LUA_API void lua_newtable (lua_State *L); +LUA_API void lua_getregistry (lua_State *L); +LUA_API void lua_getweakregistry (lua_State *L); /* @@ -241,8 +244,6 @@ LUA_API int lua_getweakmode (lua_State *L, int index); #define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) #define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) -#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) - #define lua_pushliteral(L, s) lua_pushlstring(L, s, \ (sizeof(s)/sizeof(lua_char))-1) -- cgit v1.2.3-55-g6feb