aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-10-04 15:51:04 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>1999-10-04 15:51:04 -0200
commit4343420d4d559a7d4cdacdbc1fd61552dcf59f04 (patch)
tree57e0bdd41e2f3a4ab70d3150022569751e3d02ad /lgc.c
parent1f7103e05d01a6a4c300a73bcfc8d9b17b2c20a4 (diff)
downloadlua-4343420d4d559a7d4cdacdbc1fd61552dcf59f04.tar.gz
lua-4343420d4d559a7d4cdacdbc1fd61552dcf59f04.tar.bz2
lua-4343420d4d559a7d4cdacdbc1fd61552dcf59f04.zip
simplified version of `gc' tag method (only for userdata now).
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c302
1 files changed, 148 insertions, 154 deletions
diff --git a/lgc.c b/lgc.c
index a710ec4f..e78f0fdb 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.25 1999/08/16 20:52:00 roberto Exp roberto $ 2** $Id: lgc.c,v 1.26 1999/09/27 18:00:25 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*/
@@ -8,8 +8,8 @@
8#include "ldo.h" 8#include "ldo.h"
9#include "lfunc.h" 9#include "lfunc.h"
10#include "lgc.h" 10#include "lgc.h"
11#include "lmem.h"
12#include "lobject.h" 11#include "lobject.h"
12#include "lref.h"
13#include "lstate.h" 13#include "lstate.h"
14#include "lstring.h" 14#include "lstring.h"
15#include "ltable.h" 15#include "ltable.h"
@@ -21,138 +21,15 @@
21static int markobject (TObject *o); 21static int markobject (TObject *o);
22 22
23 23
24 24/* mark a string; marks bigger than 1 cannot be changed */
25/* 25#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;}
26** =======================================================
27** REF mechanism
28** =======================================================
29*/
30
31
32int luaC_ref (const TObject *o, int lock) {
33 int ref;
34 if (ttype(o) == LUA_T_NIL)
35 ref = LUA_REFNIL;
36 else {
37 for (ref=0; ref<L->refSize; ref++)
38 if (L->refArray[ref].status == FREE)
39 break;
40 if (ref == L->refSize) { /* no more empty spaces? */
41 luaM_growvector(L->refArray, L->refSize, 1, struct ref, refEM, MAX_INT);
42 L->refSize++;
43 }
44 L->refArray[ref].o = *o;
45 L->refArray[ref].status = lock ? LOCK : HOLD;
46 }
47 return ref;
48}
49
50
51void lua_unref (int ref) {
52 if (ref >= 0 && ref < L->refSize)
53 L->refArray[ref].status = FREE;
54}
55
56
57const TObject *luaC_getref (int ref) {
58 if (ref == LUA_REFNIL)
59 return &luaO_nilobject;
60 if (ref >= 0 && ref < L->refSize &&
61 (L->refArray[ref].status == LOCK || L->refArray[ref].status == HOLD))
62 return &L->refArray[ref].o;
63 else
64 return NULL;
65}
66
67
68static void travlock (void) {
69 int i;
70 for (i=0; i<L->refSize; i++)
71 if (L->refArray[i].status == LOCK)
72 markobject(&L->refArray[i].o);
73}
74
75
76static int ismarked (const TObject *o) {
77 /* valid only for locked objects */
78 switch (o->ttype) {
79 case LUA_T_STRING: case LUA_T_USERDATA:
80 return o->value.ts->head.marked;
81 case LUA_T_ARRAY:
82 return o->value.a->head.marked;
83 case LUA_T_CLOSURE:
84 return o->value.cl->head.marked;
85 case LUA_T_PROTO:
86 return o->value.tf->head.marked;
87#ifdef DEBUG
88 case LUA_T_LINE: case LUA_T_CLMARK:
89 case LUA_T_CMARK: case LUA_T_PMARK:
90 LUA_INTERNALERROR("invalid type");
91#endif
92 default: /* nil, number or cproto */
93 return 1;
94 }
95}
96 26
97 27
98static void invalidaterefs (void) {
99 int i;
100 for (i=0; i<L->refSize; i++)
101 if (L->refArray[i].status == HOLD && !ismarked(&L->refArray[i].o))
102 L->refArray[i].status = COLLECTED;
103}
104
105
106
107void luaC_hashcallIM (Hash *l) {
108 TObject t;
109 ttype(&t) = LUA_T_ARRAY;
110 for (; l; l=(Hash *)l->head.next) {
111 avalue(&t) = l;
112 luaD_gcIM(&t);
113 }
114}
115
116
117void luaC_strcallIM (TaggedString *l) {
118 TObject o;
119 ttype(&o) = LUA_T_USERDATA;
120 for (; l; l=(TaggedString *)l->head.next)
121 if (l->constindex == -1) { /* is userdata? */
122 tsvalue(&o) = l;
123 luaD_gcIM(&o);
124 }
125}
126
127
128
129static GCnode *listcollect (GCnode *l) {
130 GCnode *frees = NULL;
131 while (l) {
132 GCnode *next = l->next;
133 l->marked = 0;
134 while (next && !next->marked) {
135 l->next = next->next;
136 next->next = frees;
137 frees = next;
138 next = l->next;
139 }
140 l = next;
141 }
142 return frees;
143}
144
145
146/*
147** mark a string; marks bigger than 1 cannot be changed.
148*/
149#define strmark(s) {if ((s)->head.marked == 0) (s)->head.marked = 1;}
150
151 28
152static void protomark (TProtoFunc *f) { 29static void protomark (TProtoFunc *f) {
153 if (!f->head.marked) { 30 if (!f->marked) {
154 int i; 31 int i;
155 f->head.marked = 1; 32 f->marked = 1;
156 strmark(f->source); 33 strmark(f->source);
157 for (i=f->nconsts-1; i>=0; i--) 34 for (i=f->nconsts-1; i>=0; i--)
158 markobject(&f->consts[i]); 35 markobject(&f->consts[i]);
@@ -161,9 +38,9 @@ static void protomark (TProtoFunc *f) {
161 38
162 39
163static void closuremark (Closure *f) { 40static void closuremark (Closure *f) {
164 if (!f->head.marked) { 41 if (!f->marked) {
165 int i; 42 int i;
166 f->head.marked = 1; 43 f->marked = 1;
167 for (i=f->nelems; i>=0; i--) 44 for (i=f->nelems; i>=0; i--)
168 markobject(&f->consts[i]); 45 markobject(&f->consts[i]);
169 } 46 }
@@ -171,9 +48,9 @@ static void closuremark (Closure *f) {
171 48
172 49
173static void hashmark (Hash *h) { 50static void hashmark (Hash *h) {
174 if (!h->head.marked) { 51 if (!h->marked) {
175 int i; 52 int i;
176 h->head.marked = 1; 53 h->marked = 1;
177 for (i=nhash(h)-1; i>=0; i--) { 54 for (i=nhash(h)-1; i>=0; i--) {
178 Node *n = node(h,i); 55 Node *n = node(h,i);
179 if (ttype(ref(n)) != LUA_T_NIL) { 56 if (ttype(ref(n)) != LUA_T_NIL) {
@@ -187,7 +64,7 @@ static void hashmark (Hash *h) {
187 64
188static void globalmark (void) { 65static void globalmark (void) {
189 TaggedString *g; 66 TaggedString *g;
190 for (g=(TaggedString *)L->rootglobal.next; g; g=(TaggedString *)g->head.next){ 67 for (g=L->rootglobal; g; g=g->next) {
191 LUA_ASSERT(g->constindex >= 0, "userdata in global list"); 68 LUA_ASSERT(g->constindex >= 0, "userdata in global list");
192 if (g->u.s.globalval.ttype != LUA_T_NIL) { 69 if (g->u.s.globalval.ttype != LUA_T_NIL) {
193 markobject(&g->u.s.globalval); 70 markobject(&g->u.s.globalval);
@@ -197,6 +74,21 @@ static void globalmark (void) {
197} 74}
198 75
199 76
77static void travstack (void) {
78 StkId i;
79 for (i = (L->stack.top-1)-L->stack.stack; i>=0; i--)
80 markobject(L->stack.stack+i);
81}
82
83
84static void travlock (void) {
85 int i;
86 for (i=0; i<L->refSize; i++)
87 if (L->refArray[i].status == LOCK)
88 markobject(&L->refArray[i].o);
89}
90
91
200static int markobject (TObject *o) { 92static int markobject (TObject *o) {
201 switch (ttype(o)) { 93 switch (ttype(o)) {
202 case LUA_T_USERDATA: case LUA_T_STRING: 94 case LUA_T_USERDATA: case LUA_T_STRING:
@@ -217,36 +109,138 @@ static int markobject (TObject *o) {
217} 109}
218 110
219 111
112static void collectproto (void) {
113 TProtoFunc **p = &L->rootproto;
114 TProtoFunc *next;
115 while ((next = *p) != NULL) {
116 if (next->marked) {
117 next->marked = 0;
118 p = &next->next;
119 }
120 else {
121 *p = next->next;
122 luaF_freeproto(next);
123 }
124 }
125}
126
127
128static void collectclosure (void) {
129 Closure **p = &L->rootcl;
130 Closure *next;
131 while ((next = *p) != NULL) {
132 if (next->marked) {
133 next->marked = 0;
134 p = &next->next;
135 }
136 else {
137 *p = next->next;
138 luaF_freeclosure(next);
139 }
140 }
141}
142
143
144static void collecttable (void) {
145 Hash **p = &L->roottable;
146 Hash *next;
147 while ((next = *p) != NULL) {
148 if (next->marked) {
149 next->marked = 0;
150 p = &next->next;
151 }
152 else {
153 *p = next->next;
154 luaH_free(next);
155 }
156 }
157}
158
159
160static void clear_global_list (void) {
161 TaggedString **p = &L->rootglobal;
162 TaggedString *next;
163 while ((next = *p) != NULL) {
164 if (next->marked) p = &next->next;
165 else *p = next->next;
166 }
167}
168
169
170/*
171** collect all elements with `marked' < `limit'.
172** with limit=1, that means all unmarked elements;
173** with limit=MAX_INT, that means all elements (but EMPTY).
174*/
175static void collectstring (int limit) {
176 TObject o; /* to call userdata 'gc' tag method */
177 int i;
178 ttype(&o) = LUA_T_USERDATA;
179 clear_global_list();
180 for (i=0; i<NUM_HASHS; i++) {
181 stringtable *tb = &L->string_root[i];
182 int j;
183 for (j=0; j<tb->size; j++) {
184 TaggedString *t = tb->hash[j];
185 if (t == NULL) continue;
186 if (t->marked < limit) {
187 if (t->constindex == -1) { /* is userdata? */
188 tsvalue(&o) = t;
189 luaD_gcIM(&o);
190 }
191 luaS_free(t);
192 tb->hash[j] = &luaS_EMPTY;
193 }
194 else if (t->marked == 1)
195 t->marked = 0;
196 }
197 }
198}
199
200
201#ifdef LUA_COMPAT_GC
202static void tableTM (void) {
203 Hash *p;
204 TObject o;
205 ttype(&o) = LUA_T_ARRAY;
206 for (p = L->roottable; p; p = p->next) {
207 if (!p->marked) {
208 avalue(&o) = p;
209 luaD_gcIM(&o);
210 }
211 }
212}
213#else
214#define tableTM() /* do nothing */
215#endif
216
217
220 218
221static void markall (void) { 219static void markall (void) {
222 luaD_travstack(markobject); /* mark stack objects */ 220 travstack(); /* mark stack objects */
223 globalmark(); /* mark global variable values and names */ 221 globalmark(); /* mark global variable values and names */
224 travlock(); /* mark locked objects */ 222 travlock(); /* mark locked objects */
225 luaT_travtagmethods(markobject); /* mark fallbacks */ 223 luaT_travtagmethods(markobject); /* mark tag methods */
224}
225
226
227void luaC_collect (int all) {
228 L->GCthreshold *= 4; /* to avoid GC during GC */
229 tableTM(); /* call TM for tables (if LUA_COMPAT_GC) */
230 collecttable();
231 collectstring(all?MAX_INT:1);
232 collectproto();
233 collectclosure();
234 luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */
226} 235}
227 236
228 237
229long lua_collectgarbage (long limit) { 238long lua_collectgarbage (long limit) {
230 unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */ 239 unsigned long recovered = L->nblocks; /* to subtract nblocks after gc */
231 Hash *freetable;
232 TaggedString *freestr;
233 TProtoFunc *freefunc;
234 Closure *freeclos;
235 markall(); 240 markall();
236 invalidaterefs(); 241 luaR_invalidaterefs();
237 freestr = luaS_collector(); 242 luaC_collect(0);
238 freetable = (Hash *)listcollect(&(L->roottable)); 243 recovered = recovered - L->nblocks;
239 freefunc = (TProtoFunc *)listcollect(&(L->rootproto));
240 freeclos = (Closure *)listcollect(&(L->rootcl));
241 L->GCthreshold *= 4; /* to avoid GC during GC */
242 luaC_hashcallIM(freetable); /* GC tag methods for tables */
243 luaC_strcallIM(freestr); /* GC tag methods for userdata */
244 luaD_gcIM(&luaO_nilobject); /* GC tag method for nil (signal end of GC) */
245 luaH_free(freetable);
246 luaS_free(freestr);
247 luaF_freeproto(freefunc);
248 luaF_freeclosure(freeclos);
249 recovered = recovered-L->nblocks;
250 L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit; 244 L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit;
251 return recovered; 245 return recovered;
252} 246}