summaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-08-07 17:21:34 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-08-07 17:21:34 -0300
commitd9e61e8ceafe8c3f6ad936979719ca7c446ce228 (patch)
tree0808ada3d7b7219022b9002503894c76c7253df6 /lgc.c
parent397905ef8694ec716a51acebc993bb625340d388 (diff)
downloadlua-d9e61e8ceafe8c3f6ad936979719ca7c446ce228.tar.gz
lua-d9e61e8ceafe8c3f6ad936979719ca7c446ce228.tar.bz2
lua-d9e61e8ceafe8c3f6ad936979719ca7c446ce228.zip
new algorithm for traversing in GC to avoid deep recursion calls
Diffstat (limited to 'lgc.c')
-rw-r--r--lgc.c148
1 files changed, 86 insertions, 62 deletions
diff --git a/lgc.c b/lgc.c
index 7bdc5790..d884d224 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.58 2000/06/26 19:28:31 roberto Exp roberto $ 2** $Id: lgc.c,v 1.59 2000/06/30 14:35:17 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*/
@@ -20,97 +20,94 @@
20#include "ltm.h" 20#include "ltm.h"
21 21
22 22
23typedef struct GCState {
24 Hash *tmark; /* list of marked tables to be visited */
25 Closure *cmark; /* list of marked closures to be visited */
26} GCState;
23 27
24 28
25static int markobject (lua_State *L, TObject *o); 29
30static int markobject (GCState *st, TObject *o);
26 31
27 32
28/* mark a string; marks larger than 1 cannot be changed */ 33/* mark a string; marks larger than 1 cannot be changed */
29#define strmark(L, s) {if ((s)->marked == 0) (s)->marked = 1;} 34#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;}
30 35
31 36
32 37
33static void protomark (lua_State *L, Proto *f) { 38static void protomark (Proto *f) {
34 if (!f->marked) { 39 if (!f->marked) {
35 int i; 40 int i;
36 f->marked = 1; 41 f->marked = 1;
37 strmark(L, f->source); 42 strmark(f->source);
38 for (i=0; i<f->nkstr; i++) 43 for (i=0; i<f->nkstr; i++)
39 strmark(L, f->kstr[i]); 44 strmark(f->kstr[i]);
40 for (i=0; i<f->nkproto; i++) 45 for (i=0; i<f->nkproto; i++)
41 protomark(L, f->kproto[i]); 46 protomark(f->kproto[i]);
42 if (f->locvars) { /* is there debug information? */ 47 if (f->locvars) { /* is there debug information? */
43 LocVar *lv; 48 LocVar *lv;
44 for (lv=f->locvars; lv->pc != -1; lv++) /* mark local-variable names */ 49 for (lv=f->locvars; lv->pc != -1; lv++) /* mark local-variable names */
45 if (lv->varname) strmark(L, lv->varname); 50 if (lv->varname) strmark(lv->varname);
46 } 51 }
47 } 52 }
48} 53}
49 54
50 55
51static void closuremark (lua_State *L, Closure *f) { 56static void markstack (lua_State *L, GCState *st) {
52 if (!f->marked) {
53 int i = f->nupvalues;
54 f->marked = 1;
55 while (i--)
56 markobject(L, &f->upvalue[i]);
57 }
58}
59
60
61static void tablemark (lua_State *L, Hash *h) {
62 if (!h->marked) {
63 int i;
64 h->marked = 1;
65 for (i=h->size-1; i>=0; i--) {
66 Node *n = node(h,i);
67 if (ttype(key(n)) != TAG_NIL) {
68 if (ttype(val(n)) == TAG_NIL)
69 luaH_remove(h, key(n)); /* dead element; try to remove it */
70 markobject(L, &n->key);
71 markobject(L, &n->val);
72 }
73 }
74 }
75}
76
77
78static void travstack (lua_State *L) {
79 StkId o; 57 StkId o;
80 for (o=L->stack; o<L->top; o++) 58 for (o=L->stack; o<L->top; o++)
81 markobject(L, o); 59 markobject(st, o);
82} 60}
83 61
84 62
85static void travlock (lua_State *L) { 63static void marklock (lua_State *L, GCState *st) {
86 int i; 64 int i;
87 for (i=0; i<L->refSize; i++) { 65 for (i=0; i<L->refSize; i++) {
88 if (L->refArray[i].st == LOCK) 66 if (L->refArray[i].st == LOCK)
89 markobject(L, &L->refArray[i].o); 67 markobject(st, &L->refArray[i].o);
68 }
69}
70
71
72static void marktagmethods (lua_State *L, GCState *st) {
73 int e;
74 for (e=0; e<IM_N; e++) {
75 int t;
76 for (t=0; t<=L->last_tag; t++)
77 markobject(st, luaT_getim(L, t,e));
90 } 78 }
91} 79}
92 80
93 81
94static int markobject (lua_State *L, TObject *o) { 82static int markobject (GCState *st, TObject *o) {
95 switch (ttype(o)) { 83 switch (ttype(o)) {
96 case TAG_USERDATA: case TAG_STRING: 84 case TAG_USERDATA: case TAG_STRING:
97 strmark(L, tsvalue(o)); 85 strmark(tsvalue(o));
98 break;
99 case TAG_TABLE:
100 tablemark(L, hvalue(o));
101 break; 86 break;
102 case TAG_LCLOSURE: 87 case TAG_TABLE: {
103 protomark(L, clvalue(o)->f.l); 88 if (!ismarked(hvalue(o))) {
104 closuremark(L, clvalue(o)); 89 hvalue(o)->mark = st->tmark; /* chain it in list of marked */
90 st->tmark = hvalue(o);
91 }
105 break; 92 break;
93 }
106 case TAG_LMARK: { 94 case TAG_LMARK: {
107 Closure *cl = infovalue(o)->func; 95 Closure *cl = infovalue(o)->func;
108 protomark(L, cl->f.l); 96 if (!ismarked(cl)) {
109 closuremark(L, cl); 97 protomark(cl->f.l);
98 cl->mark = st->cmark; /* chain it for later traversal */
99 st->cmark = cl;
100 }
110 break; 101 break;
111 } 102 }
103 case TAG_LCLOSURE:
104 protomark(clvalue(o)->f.l);
105 /* go through */
112 case TAG_CCLOSURE: case TAG_CMARK: 106 case TAG_CCLOSURE: case TAG_CMARK:
113 closuremark(L, clvalue(o)); 107 if (!ismarked(clvalue(o))) {
108 clvalue(o)->mark = st->cmark; /* chain it for later traversal */
109 st->cmark = clvalue(o);
110 }
114 break; 111 break;
115 default: break; /* numbers, etc */ 112 default: break; /* numbers, etc */
116 } 113 }
@@ -118,6 +115,41 @@ static int markobject (lua_State *L, TObject *o) {
118} 115}
119 116
120 117
118static void markall (lua_State *L) {
119 GCState st;
120 st.cmark = NULL;
121 st.tmark = L->gt; /* put table of globals in mark list */
122 L->gt->mark = NULL;
123 marktagmethods(L, &st); /* mark tag methods */
124 markstack(L, &st); /* mark stack objects */
125 marklock(L, &st); /* mark locked objects */
126 for (;;) { /* mark tables and closures */
127 if (st.cmark) {
128 int i;
129 Closure *f = st.cmark; /* get first closure from list */
130 st.cmark = f->mark; /* remove it from list */
131 for (i=0; i<f->nupvalues; i++) /* mark its upvalues */
132 markobject(&st, &f->upvalue[i]);
133 }
134 else if (st.tmark) {
135 int i;
136 Hash *h = st.tmark; /* get first table from list */
137 st.tmark = h->mark; /* remove it from list */
138 for (i=0; i<h->size; i++) {
139 Node *n = node(h, i);
140 if (ttype(key(n)) != TAG_NIL) {
141 if (ttype(val(n)) == TAG_NIL)
142 luaH_remove(h, key(n)); /* dead element; try to remove it */
143 markobject(&st, &n->key);
144 markobject(&st, &n->val);
145 }
146 }
147 }
148 else break; /* nothing else to mark */
149 }
150}
151
152
121static void collectproto (lua_State *L) { 153static void collectproto (lua_State *L) {
122 Proto **p = &L->rootproto; 154 Proto **p = &L->rootproto;
123 Proto *next; 155 Proto *next;
@@ -138,8 +170,8 @@ static void collectclosure (lua_State *L) {
138 Closure **p = &L->rootcl; 170 Closure **p = &L->rootcl;
139 Closure *next; 171 Closure *next;
140 while ((next = *p) != NULL) { 172 while ((next = *p) != NULL) {
141 if (next->marked) { 173 if (ismarked(next)) {
142 next->marked = 0; 174 next->mark = next; /* unmark */
143 p = &next->next; 175 p = &next->next;
144 } 176 }
145 else { 177 else {
@@ -154,8 +186,8 @@ static void collecttable (lua_State *L) {
154 Hash **p = &L->roottable; 186 Hash **p = &L->roottable;
155 Hash *next; 187 Hash *next;
156 while ((next = *p) != NULL) { 188 while ((next = *p) != NULL) {
157 if (next->marked) { 189 if (ismarked(next)) {
158 next->marked = 0; 190 next->mark = next; /* unmark */
159 p = &next->next; 191 p = &next->next;
160 } 192 }
161 else { 193 else {
@@ -256,14 +288,6 @@ static void callgcTMudata (lua_State *L) {
256} 288}
257 289
258 290
259static void markall (lua_State *L) {
260 luaT_travtagmethods(L, markobject); /* mark tag methods */
261 travstack(L); /* mark stack objects */
262 tablemark(L, L->gt); /* mark global variables */
263 travlock(L); /* mark locked objects */
264}
265
266
267void luaC_collect (lua_State *L, int all) { 291void luaC_collect (lua_State *L, int all) {
268 int oldah = L->allowhooks; 292 int oldah = L->allowhooks;
269 L->allowhooks = 0; /* stop debug hooks during GC */ 293 L->allowhooks = 0; /* stop debug hooks during GC */