2 ** $Id: lgc.c,v 1.18 1998/03/09 21:49:52 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
)
35 if (ttype(o
) == LUA_T_NIL
)
36 ref
= -1; /* special ref for nil */
38 for (ref
=0; ref
<L
->refSize
; ref
++)
39 if (L
->refArray
[ref
].status
== FREE
)
41 /* no more empty spaces */ {
42 int oldSize
= L
->refSize
;
43 L
->refSize
= luaM_growvector(&L
->refArray
, L
->refSize
, struct ref
,
45 for (ref
=oldSize
; ref
<L
->refSize
; ref
++)
46 L
->refArray
[ref
].status
= FREE
;
49 L
->refArray
[ref
].o
= *o
;
50 L
->refArray
[ref
].status
= lock
? LOCK
: HOLD
;
56 void lua_unref (int ref
)
58 if (ref
>= 0 && ref
< L
->refSize
)
59 L
->refArray
[ref
].status
= FREE
;
63 TObject
* luaC_getref (int ref
)
66 return &luaO_nilobject
;
67 if (ref
>= 0 && ref
< L
->refSize
&&
68 (L
->refArray
[ref
].status
== LOCK
|| L
->refArray
[ref
].status
== HOLD
))
69 return &L
->refArray
[ref
].o
;
75 static void travlock (void)
78 for (i
=0; i
<L
->refSize
; i
++)
79 if (L
->refArray
[i
].status
== LOCK
)
80 markobject(&L
->refArray
[i
].o
);
84 static int ismarked (TObject
*o
)
86 /* valid only for locked objects */
88 case LUA_T_STRING
: case LUA_T_USERDATA
:
89 return o
->value
.ts
->head
.marked
;
91 return o
->value
.a
->head
.marked
;
93 return o
->value
.cl
->head
.marked
;
95 return o
->value
.tf
->head
.marked
;
97 case LUA_T_LINE
: case LUA_T_CLMARK
:
98 case LUA_T_CMARK
: case LUA_T_PMARK
:
99 LUA_INTERNALERROR("invalid type");
101 default: /* nil, number or cproto */
107 static void invalidaterefs (void)
110 for (i
=0; i
<L
->refSize
; i
++)
111 if (L
->refArray
[i
].status
== HOLD
&& !ismarked(&L
->refArray
[i
].o
))
112 L
->refArray
[i
].status
= COLLECTED
;
117 void luaC_hashcallIM (Hash
*l
)
120 ttype(&t
) = LUA_T_ARRAY
;
121 for (; l
; l
=(Hash
*)l
->head
.next
) {
128 void luaC_strcallIM (TaggedString
*l
)
131 ttype(&o
) = LUA_T_USERDATA
;
132 for (; l
; l
=(TaggedString
*)l
->head
.next
)
133 if (l
->constindex
== -1) { /* is userdata? */
141 static GCnode
*listcollect (GCnode
*l
)
143 GCnode
*frees
= NULL
;
145 GCnode
*next
= l
->next
;
147 while (next
&& !next
->marked
) {
148 l
->next
= next
->next
;
159 static void strmark (TaggedString
*s
)
166 static void protomark (TProtoFunc
*f
)
168 if (!f
->head
.marked
) {
169 LocVar
*v
= f
->locvars
;
173 strmark(f
->fileName
);
174 for (i
=0; i
<f
->nconsts
; i
++)
175 markobject(&f
->consts
[i
]);
177 for (; v
->line
!= -1; v
++)
185 static void closuremark (Closure
*f
)
187 if (!f
->head
.marked
) {
190 for (i
=f
->nelems
; i
>=0; i
--)
191 markobject(&f
->consts
[i
]);
196 static void hashmark (Hash
*h
)
198 if (!h
->head
.marked
) {
201 for (i
=0; i
<nhash(h
); i
++) {
203 if (ttype(ref(n
)) != LUA_T_NIL
) {
212 static void globalmark (void)
215 for (g
=(TaggedString
*)L
->rootglobal
.next
; g
; g
=(TaggedString
*)g
->head
.next
){
216 LUA_ASSERT(g
->constindex
>= 0, "userdata in global list");
217 if (g
->u
.s
.globalval
.ttype
!= LUA_T_NIL
) {
218 markobject(&g
->u
.s
.globalval
);
219 strmark(g
); /* cannot collect non nil global variables */
225 static int markobject (TObject
*o
)
228 case LUA_T_USERDATA
: case LUA_T_STRING
:
234 case LUA_T_CLOSURE
: case LUA_T_CLMARK
:
235 closuremark(o
->value
.cl
);
237 case LUA_T_PROTO
: case LUA_T_PMARK
:
238 protomark(o
->value
.tf
);
240 default: break; /* numbers, cprotos, etc */
247 static void markall (void)
249 luaD_travstack(markobject
); /* mark stack objects */
250 globalmark(); /* mark global variable values and names */
251 travlock(); /* mark locked objects */
252 luaT_travtagmethods(markobject
); /* mark fallbacks */
256 long lua_collectgarbage (long limit
)
258 unsigned long recovered
= L
->nblocks
; /* to subtract nblocks after gc */
260 TaggedString
*freestr
;
261 TProtoFunc
*freefunc
;
265 freestr
= luaS_collector();
266 freetable
= (Hash
*)listcollect(&(L
->roottable
));
267 freefunc
= (TProtoFunc
*)listcollect(&(L
->rootproto
));
268 freeclos
= (Closure
*)listcollect(&(L
->rootcl
));
269 L
->GCthreshold
*= 4; /* to avoid GC during GC */
270 luaC_hashcallIM(freetable
); /* GC tag methods for tables */
271 luaC_strcallIM(freestr
); /* GC tag methods for userdata */
272 luaD_gcIM(&luaO_nilobject
); /* GC tag method for nil (signal end of GC) */
273 luaH_free(freetable
);
275 luaF_freeproto(freefunc
);
276 luaF_freeclosure(freeclos
);
277 recovered
= recovered
-L
->nblocks
;
278 L
->GCthreshold
= (limit
== 0) ? 2*L
->nblocks
: L
->nblocks
+limit
;
283 void luaC_checkGC (void)
285 if (L
->nblocks
>= L
->GCthreshold
)
286 lua_collectgarbage(0);