aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-04-17 14:35:54 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2001-04-17 14:35:54 -0300
commitbeee01b170c5fea9ed4527b28b9221d2df1baaba (patch)
tree82263b6e128ffe09fe3da63de16c626522320dfc
parent6473f965ca699719b3b9908008f15da48cc2e6f1 (diff)
downloadlua-beee01b170c5fea9ed4527b28b9221d2df1baaba.tar.gz
lua-beee01b170c5fea9ed4527b28b9221d2df1baaba.tar.bz2
lua-beee01b170c5fea9ed4527b28b9221d2df1baaba.zip
re-implementation of refs through weak tables
-rw-r--r--lapi.c76
-rw-r--r--lgc.c35
-rw-r--r--lstate.c25
-rw-r--r--lstate.h22
-rw-r--r--ltests.c15
-rw-r--r--lua.h25
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 @@
1/* 1/*
2** $Id: lapi.c,v 1.138 2001/04/11 14:42:41 roberto Exp roberto $ 2** $Id: lapi.c,v 1.139 2001/04/11 18:39:37 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -417,21 +417,18 @@ LUA_API void lua_getglobals (lua_State *L) {
417 417
418 418
419LUA_API int lua_getref (lua_State *L, int ref) { 419LUA_API int lua_getref (lua_State *L, int ref) {
420 int status = 1; 420 int status;
421 lua_lock(L); 421 lua_lock(L);
422 if (ref == LUA_REFNIL) { 422 if (ref == LUA_REFNIL) {
423 setnilvalue(L->top); 423 setnilvalue(L->top);
424 api_incr_top(L); 424 status = 1;
425 } 425 }
426 else { 426 else {
427 api_check(L, 0 <= ref && ref < G(L)->nref); 427 setobj(L->top, luaH_getnum(G(L)->weakregistry, ref));
428 if (G(L)->refArray[ref].st != LOCK && G(L)->refArray[ref].st != HOLD) 428 status = (ttype(L->top) != LUA_TNIL);
429 status = 0;
430 else {
431 setobj(L->top, &G(L)->refArray[ref].o);
432 api_incr_top(L);
433 }
434 } 429 }
430 if (status)
431 api_incr_top(L);
435 lua_unlock(L); 432 lua_unlock(L);
436 return status; 433 return status;
437} 434}
@@ -445,6 +442,22 @@ LUA_API void lua_newtable (lua_State *L) {
445} 442}
446 443
447 444
445LUA_API void lua_getregistry (lua_State *L) {
446 lua_lock(L);
447 sethvalue(L->top, G(L)->registry);
448 api_incr_top(L);
449 lua_unlock(L);
450}
451
452
453LUA_API void lua_getweakregistry (lua_State *L) {
454 lua_lock(L);
455 sethvalue(L->top, G(L)->weakregistry);
456 api_incr_top(L);
457 lua_unlock(L);
458}
459
460
448 461
449/* 462/*
450** set functions (stack -> Lua) 463** set functions (stack -> Lua)
@@ -508,25 +521,26 @@ LUA_API void lua_setglobals (lua_State *L) {
508 521
509LUA_API int lua_ref (lua_State *L, int lock) { 522LUA_API int lua_ref (lua_State *L, int lock) {
510 int ref; 523 int ref;
511 lua_lock(L); 524 if (lua_isnil(L, -1)) {
512 api_checknelems(L, 1); 525 lua_pop(L, 1);
513 if (ttype(L->top-1) == LUA_TNIL)
514 ref = LUA_REFNIL; 526 ref = LUA_REFNIL;
527 }
515 else { 528 else {
516 if (G(L)->refFree != NONEXT) { /* is there a free place? */ 529 lua_getweakregistry(L);
517 ref = G(L)->refFree; 530 ref = lua_getn(L, -1) + 1;
518 G(L)->refFree = G(L)->refArray[ref].st; 531 lua_pushvalue(L, -2);
519 } 532 lua_rawseti(L, -2, ref);
520 else { /* no more free places */ 533 if (lock) {
521 luaM_growvector(L, G(L)->refArray, G(L)->nref, G(L)->sizeref, struct Ref, 534 lua_getregistry(L);
522 MAX_INT, l_s("reference table overflow")); 535 lua_pushvalue(L, -3);
523 ref = G(L)->nref++; 536 lua_rawseti(L, -2, ref);
537 lua_pop(L, 1); /* remove registry */
524 } 538 }
525 setobj(&G(L)->refArray[ref].o, L->top-1); 539 lua_pushliteral(L, "n");
526 G(L)->refArray[ref].st = lock ? LOCK : HOLD; 540 lua_pushnumber(L, ref);
541 lua_settable(L, -3);
542 lua_pop(L, 2);
527 } 543 }
528 L->top--;
529 lua_unlock(L);
530 return ref; 544 return ref;
531} 545}
532 546
@@ -671,13 +685,15 @@ LUA_API void lua_error (lua_State *L, const l_char *s) {
671 685
672 686
673LUA_API void lua_unref (lua_State *L, int ref) { 687LUA_API void lua_unref (lua_State *L, int ref) {
674 lua_lock(L);
675 if (ref >= 0) { 688 if (ref >= 0) {
676 api_check(L, ref < G(L)->nref && G(L)->refArray[ref].st < 0); 689 lua_getregistry(L);
677 G(L)->refArray[ref].st = G(L)->refFree; 690 lua_pushnil(L);
678 G(L)->refFree = ref; 691 lua_rawseti(L, -2, ref);
692 lua_getweakregistry(L);
693 lua_pushnil(L);
694 lua_rawseti(L, -2, ref);
695 lua_pop(L, 2); /* remove both registries */
679 } 696 }
680 lua_unlock(L);
681} 697}
682 698
683 699
diff --git a/lgc.c b/lgc.c
index a7f96f8c..0237b88c 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.95 2001/03/26 14:31:49 roberto Exp roberto $ 2** $Id: lgc.c,v 1.96 2001/04/11 14:42:41 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -111,15 +111,6 @@ static void markstacks (lua_State *L, GCState *st) {
111} 111}
112 112
113 113
114static void marklock (global_State *G, GCState *st) {
115 int i;
116 for (i=0; i<G->nref; i++) {
117 if (G->refArray[i].st == LOCK)
118 markobject(st, &G->refArray[i].o);
119 }
120}
121
122
123static void marktagmethods (global_State *G, GCState *st) { 114static void marktagmethods (global_State *G, GCState *st) {
124 int t; 115 int t;
125 for (t=0; t<G->ntag; t++) { 116 for (t=0; t<G->ntag; t++) {
@@ -176,8 +167,9 @@ static void markall (lua_State *L) {
176 st.tmark = NULL; 167 st.tmark = NULL;
177 marktagmethods(G(L), &st); /* mark tag methods */ 168 marktagmethods(G(L), &st); /* mark tag methods */
178 markstacks(L, &st); /* mark all stacks */ 169 markstacks(L, &st); /* mark all stacks */
179 marklock(G(L), &st); /* mark locked objects */
180 marktable(&st, G(L)->type2tag); 170 marktable(&st, G(L)->type2tag);
171 marktable(&st, G(L)->registry);
172 marktable(&st, G(L)->weakregistry);
181 for (;;) { /* mark tables and closures */ 173 for (;;) { /* mark tables and closures */
182 if (st.cmark) { 174 if (st.cmark) {
183 Closure *f = st.cmark; /* get first closure from list */ 175 Closure *f = st.cmark; /* get first closure from list */
@@ -208,26 +200,6 @@ static int hasmark (const TObject *o) {
208} 200}
209 201
210 202
211/* macro for internal debugging; check if a link of free refs is valid */
212#define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n))
213
214static void invalidaterefs (global_State *G) {
215 int n = G->nref;
216 int i;
217 for (i=0; i<n; i++) {
218 struct Ref *r = &G->refArray[i];
219 if (r->st == HOLD && !hasmark(&r->o))
220 r->st = COLLECTED;
221 lua_assert((r->st == LOCK && hasmark(&r->o)) ||
222 (r->st == HOLD && hasmark(&r->o)) ||
223 r->st == COLLECTED ||
224 r->st == NONEXT ||
225 (r->st < n && VALIDLINK(L, G->refArray[r->st].st, n)));
226 }
227 lua_assert(VALIDLINK(L, G->refFree, n));
228}
229
230
231static void invalidatetable (Hash *h) { 203static void invalidatetable (Hash *h) {
232 int i; 204 int i;
233 for (i=0; i<h->size; i++) { 205 for (i=0; i<h->size; i++) {
@@ -408,7 +380,6 @@ void luaC_collect (lua_State *L, int all) {
408 380
409void luaC_collectgarbage (lua_State *L) { 381void luaC_collectgarbage (lua_State *L) {
410 markall(L); 382 markall(L);
411 invalidaterefs(G(L)); /* check unlocked references */
412 invalidatetables(G(L)); 383 invalidatetables(G(L));
413 luaC_collect(L, 0); 384 luaC_collect(L, 0);
414 checkMbuffer(L); 385 checkMbuffer(L);
diff --git a/lstate.c b/lstate.c
index 1006dbec..63e15283 100644
--- a/lstate.c
+++ b/lstate.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.c,v 1.60 2001/03/09 18:05:05 roberto Exp roberto $ 2** $Id: lstate.c,v 1.61 2001/03/26 14:31:49 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -30,20 +30,6 @@ static void close_state (lua_State *L, lua_State *OL);
30 30
31 31
32/* 32/*
33** initialize ref array and registry
34*/
35#define INIT_REFSIZE 4
36
37static void ref_init (lua_State *L) {
38 G(L)->refArray = luaM_newvector(L, INIT_REFSIZE, struct Ref);
39 G(L)->sizeref = INIT_REFSIZE;
40 sethvalue(&G(L)->refArray[0].o, luaH_new(L, 0));
41 G(L)->refArray[0].st = LOCK;
42 G(L)->nref = 1;
43}
44
45
46/*
47** open parts that may cause memory-allocation errors 33** open parts that may cause memory-allocation errors
48*/ 34*/
49static void f_luaopen (lua_State *L, void *ud) { 35static void f_luaopen (lua_State *L, void *ud) {
@@ -74,18 +60,16 @@ static void f_luaopen (lua_State *L, void *ud) {
74 G(L)->TMtable = NULL; 60 G(L)->TMtable = NULL;
75 G(L)->sizeTM = 0; 61 G(L)->sizeTM = 0;
76 G(L)->ntag = 0; 62 G(L)->ntag = 0;
77 G(L)->refArray = NULL;
78 G(L)->nref = 0;
79 G(L)->sizeref = 0;
80 G(L)->refFree = NONEXT;
81 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State); 63 G(L)->nblocks = sizeof(lua_State) + sizeof(global_State);
82 luaD_init(L, so->stacksize); /* init stack */ 64 luaD_init(L, so->stacksize); /* init stack */
83 L->gt = luaH_new(L, 10); /* table of globals */ 65 L->gt = luaH_new(L, 10); /* table of globals */
84 G(L)->type2tag = luaH_new(L, 10); 66 G(L)->type2tag = luaH_new(L, 10);
67 G(L)->registry = luaH_new(L, 0);
68 G(L)->weakregistry = luaH_new(L, 0);
69 G(L)->weakregistry->weakmode = LUA_WEAK_VALUE; /* make weakregistry weak */
85 luaS_init(L); 70 luaS_init(L);
86 luaX_init(L); 71 luaX_init(L);
87 luaT_init(L); 72 luaT_init(L);
88 ref_init(L);
89 G(L)->GCthreshold = 4*G(L)->nblocks; 73 G(L)->GCthreshold = 4*G(L)->nblocks;
90 } 74 }
91} 75}
@@ -133,7 +117,6 @@ static void close_state (lua_State *L, lua_State *OL) {
133 lua_assert(G(L)->roottable == NULL); 117 lua_assert(G(L)->roottable == NULL);
134 luaS_freeall(L); 118 luaS_freeall(L);
135 luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM); 119 luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM);
136 luaM_freearray(L, G(L)->refArray, G(L)->sizeref, struct Ref);
137 luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char); 120 luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char);
138 luaM_freelem(NULL, L->G, global_State); 121 luaM_freelem(NULL, L->G, global_State);
139 } 122 }
diff --git a/lstate.h b/lstate.h
index 69fd02ad..7c0e808d 100644
--- a/lstate.h
+++ b/lstate.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstate.h,v 1.54 2001/03/02 17:27:50 roberto Exp roberto $ 2** $Id: lstate.h,v 1.55 2001/03/07 18:09:25 roberto Exp roberto $
3** Global State 3** Global State
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -32,20 +32,6 @@
32#endif 32#endif
33 33
34 34
35/*
36** marks for Reference array
37*/
38#define NONEXT -1 /* to end the free list */
39#define HOLD -2
40#define COLLECTED -3
41#define LOCK -4
42
43
44struct Ref {
45 TObject o;
46 int st; /* can be LOCK, HOLD, COLLECTED, or next (for free list) */
47};
48
49 35
50struct lua_longjmp; /* defined in ldo.c */ 36struct lua_longjmp; /* defined in ldo.c */
51struct TM; /* defined in ltm.h */ 37struct TM; /* defined in ltm.h */
@@ -70,13 +56,11 @@ typedef struct global_State {
70 stringtable strt; /* hash table for strings */ 56 stringtable strt; /* hash table for strings */
71 stringtable udt; /* hash table for udata */ 57 stringtable udt; /* hash table for udata */
72 Hash *type2tag; /* hash table from type names to tags */ 58 Hash *type2tag; /* hash table from type names to tags */
59 Hash *registry; /* (strong) registry table */
60 Hash *weakregistry; /* weakregistry table */
73 struct TM *TMtable; /* table for tag methods */ 61 struct TM *TMtable; /* table for tag methods */
74 int sizeTM; /* size of TMtable */ 62 int sizeTM; /* size of TMtable */
75 int ntag; /* number of tags in TMtable */ 63 int ntag; /* number of tags in TMtable */
76 struct Ref *refArray; /* locked objects */
77 int nref; /* first unused element in refArray */
78 int sizeref; /* size of refArray */
79 int refFree; /* list of free positions in refArray */
80 lu_mem GCthreshold; 64 lu_mem GCthreshold;
81 lu_mem nblocks; /* number of `bytes' currently allocated */ 65 lu_mem nblocks; /* number of `bytes' currently allocated */
82} global_State; 66} global_State;
diff --git a/ltests.c b/ltests.c
index d012df8b..d761d065 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltests.c,v 1.77 2001/03/26 14:31:49 roberto Exp roberto $ 2** $Id: ltests.c,v 1.78 2001/04/11 14:42:41 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -383,21 +383,30 @@ static int string_query (lua_State *L) {
383 383
384 384
385static int tref (lua_State *L) { 385static int tref (lua_State *L) {
386 int level = lua_gettop(L);
386 luaL_checkany(L, 1); 387 luaL_checkany(L, 1);
387 lua_pushvalue(L, 1); 388 lua_pushvalue(L, 1);
388 lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1))); 389 lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1)));
390 assert(lua_gettop(L) == level+1); /* +1 for result */
389 return 1; 391 return 1;
390} 392}
391 393
392static int getref (lua_State *L) { 394static int getref (lua_State *L) {
393 if (lua_getref(L, luaL_check_int(L, 1))) 395 int level = lua_gettop(L);
396 if (lua_getref(L, luaL_check_int(L, 1))) {
397 assert(lua_gettop(L) == level+1);
394 return 1; 398 return 1;
395 else 399 }
400 else {
401 assert(lua_gettop(L) == level);
396 return 0; 402 return 0;
403 }
397} 404}
398 405
399static int unref (lua_State *L) { 406static int unref (lua_State *L) {
407 int level = lua_gettop(L);
400 lua_unref(L, luaL_check_int(L, 1)); 408 lua_unref(L, luaL_check_int(L, 1));
409 assert(lua_gettop(L) == level);
401 return 0; 410 return 0;
402} 411}
403 412
diff --git a/lua.h b/lua.h
index 313a32be..4bfbc336 100644
--- a/lua.h
+++ b/lua.h
@@ -1,8 +1,8 @@
1/* 1/*
2** $Id: lua.h,v 1.94 2001/04/11 14:42:41 roberto Exp roberto $ 2** $Id: lua.h,v 1.95 2001/04/11 18:39:37 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil 4** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
5** e-mail: lua@tecgraf.puc-rio.br 5** e-mail: info@lua.org
6** www: http://www.lua.org 6** www: http://www.lua.org
7** See Copyright Notice at the end of this file 7** See Copyright Notice at the end of this file
8*/ 8*/
@@ -29,24 +29,20 @@
29/* pre-defined references */ 29/* pre-defined references */
30#define LUA_NOREF (-2) 30#define LUA_NOREF (-2)
31#define LUA_REFNIL (-1) 31#define LUA_REFNIL (-1)
32#define LUA_REFREGISTRY 0
33
34/* pre-defined tags */
35#define LUA_NOTAG (-2)
36 32
37 33
38/* option for multiple returns in lua_call */ 34/* option for multiple returns in `lua_call' */
39#define LUA_MULTRET (-1) 35#define LUA_MULTRET (-1)
40 36
41 37
42/* error codes for lua_do* */ 38/* error codes for `lua_do*' and the like */
43#define LUA_ERRRUN 1 39#define LUA_ERRRUN 1
44#define LUA_ERRFILE 2 40#define LUA_ERRFILE 2
45#define LUA_ERRSYNTAX 3 41#define LUA_ERRSYNTAX 3
46#define LUA_ERRMEM 4 42#define LUA_ERRMEM 4
47#define LUA_ERRERR 5 43#define LUA_ERRERR 5
48 44
49/* weak modes */ 45/* weak-table modes */
50#define LUA_WEAK_KEY 1 46#define LUA_WEAK_KEY 1
51#define LUA_WEAK_VALUE 2 47#define LUA_WEAK_VALUE 2
52 48
@@ -67,6 +63,11 @@ typedef int (*lua_CFunction) (lua_State *L);
67#define LUA_TTABLE 4 63#define LUA_TTABLE 4
68#define LUA_TFUNCTION 5 64#define LUA_TFUNCTION 5
69 65
66/*
67** an invalid `tag'
68*/
69#define LUA_NOTAG (-2)
70
70 71
71 72
72/* 73/*
@@ -77,7 +78,7 @@ typedef int (*lua_CFunction) (lua_State *L);
77#endif 78#endif
78 79
79 80
80/* minimum stack available for a C function */ 81/* minimum Lua stack available to a C function */
81#define LUA_MINSTACK 20 82#define LUA_MINSTACK 20
82 83
83 84
@@ -163,6 +164,8 @@ LUA_API void lua_getglobals (lua_State *L);
163LUA_API void lua_gettagmethod (lua_State *L, int tag, const lua_char *event); 164LUA_API void lua_gettagmethod (lua_State *L, int tag, const lua_char *event);
164LUA_API int lua_getref (lua_State *L, int ref); 165LUA_API int lua_getref (lua_State *L, int ref);
165LUA_API void lua_newtable (lua_State *L); 166LUA_API void lua_newtable (lua_State *L);
167LUA_API void lua_getregistry (lua_State *L);
168LUA_API void lua_getweakregistry (lua_State *L);
166 169
167 170
168/* 171/*
@@ -241,8 +244,6 @@ LUA_API int lua_getweakmode (lua_State *L, int index);
241#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) 244#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL)
242#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) 245#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE)
243 246
244#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY)
245
246#define lua_pushliteral(L, s) lua_pushlstring(L, s, \ 247#define lua_pushliteral(L, s) lua_pushlstring(L, s, \
247 (sizeof(s)/sizeof(lua_char))-1) 248 (sizeof(s)/sizeof(lua_char))-1)
248 249