2 ** $Id: lgc.c,v 1.23 1999/03/04 21:17:26 roberto Exp $
4 ** See Copyright Notice in lua.h
21 static int markobject (TObject
*o
);
26 ** =======================================================
28 ** =======================================================
32 int luaC_ref (TObject
*o
, int lock
) {
34 if (ttype(o
) == LUA_T_NIL
)
35 ref
= -1; /* special ref for nil */
37 for (ref
=0; ref
<L
->refSize
; ref
++)
38 if (L
->refArray
[ref
].status
== FREE
)
40 if (ref
== L
->refSize
) { /* no more empty spaces? */
41 luaM_growvector(L
->refArray
, L
->refSize
, 1, struct ref
, refEM
, MAX_INT
);
44 L
->refArray
[ref
].o
= *o
;
45 L
->refArray
[ref
].status
= lock
? LOCK
: HOLD
;
51 void lua_unref (int ref
)
53 if (ref
>= 0 && ref
< L
->refSize
)
54 L
->refArray
[ref
].status
= FREE
;
58 TObject
* luaC_getref (int ref
)
61 return &luaO_nilobject
;
62 if (ref
>= 0 && ref
< L
->refSize
&&
63 (L
->refArray
[ref
].status
== LOCK
|| L
->refArray
[ref
].status
== HOLD
))
64 return &L
->refArray
[ref
].o
;
70 static void travlock (void)
73 for (i
=0; i
<L
->refSize
; i
++)
74 if (L
->refArray
[i
].status
== LOCK
)
75 markobject(&L
->refArray
[i
].o
);
79 static int ismarked (TObject
*o
)
81 /* valid only for locked objects */
83 case LUA_T_STRING
: case LUA_T_USERDATA
:
84 return o
->value
.ts
->head
.marked
;
86 return o
->value
.a
->head
.marked
;
88 return o
->value
.cl
->head
.marked
;
90 return o
->value
.tf
->head
.marked
;
92 case LUA_T_LINE
: case LUA_T_CLMARK
:
93 case LUA_T_CMARK
: case LUA_T_PMARK
:
94 LUA_INTERNALERROR("invalid type");
96 default: /* nil, number or cproto */
102 static void invalidaterefs (void)
105 for (i
=0; i
<L
->refSize
; i
++)
106 if (L
->refArray
[i
].status
== HOLD
&& !ismarked(&L
->refArray
[i
].o
))
107 L
->refArray
[i
].status
= COLLECTED
;
112 void luaC_hashcallIM (Hash
*l
)
115 ttype(&t
) = LUA_T_ARRAY
;
116 for (; l
; l
=(Hash
*)l
->head
.next
) {
123 void luaC_strcallIM (TaggedString
*l
)
126 ttype(&o
) = LUA_T_USERDATA
;
127 for (; l
; l
=(TaggedString
*)l
->head
.next
)
128 if (l
->constindex
== -1) { /* is userdata? */
136 static GCnode
*listcollect (GCnode
*l
)
138 GCnode
*frees
= NULL
;
140 GCnode
*next
= l
->next
;
142 while (next
&& !next
->marked
) {
143 l
->next
= next
->next
;
154 static void strmark (TaggedString
*s
)
161 static void protomark (TProtoFunc
*f
) {
162 if (!f
->head
.marked
) {
166 for (i
=0; i
<f
->nconsts
; i
++)
167 markobject(&f
->consts
[i
]);
172 static void closuremark (Closure
*f
)
174 if (!f
->head
.marked
) {
177 for (i
=f
->nelems
; i
>=0; i
--)
178 markobject(&f
->consts
[i
]);
183 static void hashmark (Hash
*h
)
185 if (!h
->head
.marked
) {
188 for (i
=0; i
<nhash(h
); i
++) {
190 if (ttype(ref(n
)) != LUA_T_NIL
) {
199 static void globalmark (void)
202 for (g
=(TaggedString
*)L
->rootglobal
.next
; g
; g
=(TaggedString
*)g
->head
.next
){
203 LUA_ASSERT(g
->constindex
>= 0, "userdata in global list");
204 if (g
->u
.s
.globalval
.ttype
!= LUA_T_NIL
) {
205 markobject(&g
->u
.s
.globalval
);
206 strmark(g
); /* cannot collect non nil global variables */
212 static int markobject (TObject
*o
)
215 case LUA_T_USERDATA
: case LUA_T_STRING
:
221 case LUA_T_CLOSURE
: case LUA_T_CLMARK
:
222 closuremark(o
->value
.cl
);
224 case LUA_T_PROTO
: case LUA_T_PMARK
:
225 protomark(o
->value
.tf
);
227 default: break; /* numbers, cprotos, etc */
234 static void markall (void)
236 luaD_travstack(markobject
); /* mark stack objects */
237 globalmark(); /* mark global variable values and names */
238 travlock(); /* mark locked objects */
239 luaT_travtagmethods(markobject
); /* mark fallbacks */
243 long lua_collectgarbage (long limit
)
245 unsigned long recovered
= L
->nblocks
; /* to subtract nblocks after gc */
247 TaggedString
*freestr
;
248 TProtoFunc
*freefunc
;
252 freestr
= luaS_collector();
253 freetable
= (Hash
*)listcollect(&(L
->roottable
));
254 freefunc
= (TProtoFunc
*)listcollect(&(L
->rootproto
));
255 freeclos
= (Closure
*)listcollect(&(L
->rootcl
));
256 L
->GCthreshold
*= 4; /* to avoid GC during GC */
257 luaC_hashcallIM(freetable
); /* GC tag methods for tables */
258 luaC_strcallIM(freestr
); /* GC tag methods for userdata */
259 luaD_gcIM(&luaO_nilobject
); /* GC tag method for nil (signal end of GC) */
260 luaH_free(freetable
);
262 luaF_freeproto(freefunc
);
263 luaF_freeclosure(freeclos
);
264 recovered
= recovered
-L
->nblocks
;
265 L
->GCthreshold
= (limit
== 0) ? 2*L
->nblocks
: L
->nblocks
+limit
;
270 void luaC_checkGC (void)
272 if (L
->nblocks
>= L
->GCthreshold
)
273 lua_collectgarbage(0);