/[cvs]/stack/gc.c
ViewVC logotype

Annotation of /stack/gc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Thu Feb 19 15:35:38 2004 UTC (20 years, 2 months ago) by masse
Branch: MAIN
CVS Tags: HEAD
File MIME type: text/plain
Extracted garbage collector to gc.c

1 masse 1.1 /*
2     stack - an interactive interpreter for a stack-based language
3     Copyright (C) 2002 Mats Alritzson and Teddy Hogeborn
4    
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9    
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13     GNU General Public License for more details.
14    
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18    
19     Authors: Mats Alritzson <masse@fukt.bth.se>
20     Teddy Hogeborn <teddy@fukt.bth.se>
21     */
22    
23     #include "stack.h"
24    
25     /* Mark values recursively.
26     Marked values are not collected by the GC. */
27     inline void gc_mark(value *val)
28     {
29     if(val==NULL || val->gc.flag.mark)
30     return;
31    
32     val->gc.flag.mark= 1;
33    
34     if(val->type==tcons) {
35     gc_mark(CAR(val));
36     gc_mark(CDR(val));
37     }
38     }
39    
40    
41     /* Start GC */
42     extern void gc_init(environment *env)
43     {
44     stackitem *new_head= NULL, *titem;
45     symbol *tsymb;
46     int i;
47    
48     if(env->interactive)
49     printf("Garbage collecting.");
50    
51     /* Mark values on stack */
52     gc_mark(env->head);
53    
54     if(env->interactive)
55     printf(".");
56    
57     /* Mark values in hashtable */
58     for(i= 0; i<HASHTBLSIZE; i++)
59     for(tsymb= env->symbols[i]; tsymb!=NULL; tsymb= tsymb->next)
60     if (tsymb->val != NULL)
61     gc_mark(tsymb->val);
62    
63     if(env->interactive)
64     printf(".");
65    
66     env->gc_count= 0;
67    
68     while(env->gc_ref!=NULL) { /* Sweep unused values */
69     if(!(env->gc_ref->item->gc.no_gc)){ /* neither mark nor protect */
70    
71     /* Remove content */
72     switch(env->gc_ref->item->type){
73     case string:
74     free(env->gc_ref->item->content.string);
75     break;
76     case tcons:
77     free(env->gc_ref->item->content.c);
78     break;
79     case port:
80     case empty:
81     case unknown:
82     case integer:
83     case tfloat:
84     case func:
85     case symb:
86     /* Symbol strings are freed when walking the hash table */
87     break;
88     }
89    
90     free(env->gc_ref->item); /* Remove from gc_ref */
91     titem= env->gc_ref->next;
92     free(env->gc_ref); /* Remove value */
93     env->gc_ref= titem;
94     continue;
95     }
96    
97     #ifdef DEBUG
98     printf("Kept value (%p)", env->gc_ref->item);
99     if(env->gc_ref->item->gc.flag.mark)
100     printf(" (marked)");
101     if(env->gc_ref->item->gc.flag.protect)
102     printf(" (protected)");
103     switch(env->gc_ref->item->type){
104     case integer:
105     printf(" integer: %d", env->gc_ref->item->content.i);
106     break;
107     case func:
108     printf(" func: %p", env->gc_ref->item->content.func);
109     break;
110     case symb:
111     printf(" symb: %s", env->gc_ref->item->content.sym->id);
112     break;
113     case tcons:
114     printf(" tcons: %p\t%p", CAR(env->gc_ref->item),
115     CDR(env->gc_ref->item));
116     break;
117     default:
118     printf(" <unknown %d>", (env->gc_ref->item->type));
119     }
120     printf("\n");
121     #endif /* DEBUG */
122    
123     /* Keep values */
124     env->gc_count += sizeof(value);
125     if(env->gc_ref->item->type==string)
126     env->gc_count += strlen(env->gc_ref->item->content.string)+1;
127    
128     titem= env->gc_ref->next;
129     env->gc_ref->next= new_head;
130     new_head= env->gc_ref;
131     new_head->item->gc.flag.mark= 0;
132     env->gc_ref= titem;
133     }
134    
135     if (env->gc_limit < env->gc_count*2)
136     env->gc_limit= env->gc_count*2;
137    
138     env->gc_ref= new_head;
139    
140     if(env->interactive)
141     printf("done (%d bytes still allocated)\n", env->gc_count);
142    
143     }
144    
145    
146     inline void gc_maybe(environment *env)
147     {
148     if(env->gc_count < env->gc_limit)
149     return;
150     else
151     return gc_init(env);
152     }
153    
154    
155     /* Protect values from GC */
156     void protect(value *val)
157     {
158     if(val==NULL || val->gc.flag.protect)
159     return;
160    
161     val->gc.flag.protect= 1;
162    
163     if(val->type==tcons) {
164     protect(CAR(val));
165     protect(CDR(val));
166     }
167     }
168    
169    
170     /* Unprotect values from GC */
171     void unprotect(value *val)
172     {
173     if(val==NULL || !(val->gc.flag.protect))
174     return;
175    
176     val->gc.flag.protect= 0;
177    
178     if(val->type==tcons) {
179     unprotect(CAR(val));
180     unprotect(CDR(val));
181     }
182     }

root@recompile.se
ViewVC Help
Powered by ViewVC 1.1.26