4 * Copyright 2004-2009 by Marc Feeley and Vincent St-Amour, All Rights Reserved.
7 #include "picobit-vm.h"
9 void init_ram_heap (void) {
11 obj o
= MAX_RAM_ENCODING
;
15 while (o
> (MIN_RAM_ENCODING
+ (glovars
+ 1) >> 1)) {
16 // we don't want to add globals to the free list, and globals occupy the
17 // beginning of memory at the rate of 2 globals per word (car and cdr)
18 ram_set_gc_tags (o
, GC_TAG_UNMARKED
);
19 ram_set_car (o
, free_list
);
24 free_list_vec
= MIN_VEC_ENCODING
;
25 ram_set_car (free_list_vec
, 0);
26 // each node of the free list must know the free length that follows it
27 // this free length is stored in words, not in bytes
28 // if we did count in bytes, the number might need more than 13 bits
29 ram_set_cdr (free_list_vec
, VEC_BYTES
>> 2);
31 for (i
=0; i
<glovars
; i
++)
32 set_global (i
, OBJ_FALSE
);
43 void mark (obj temp
) {
57 IF_GC_TRACE(printf ("push stack=%d visit=%d (tag=%d)\n", stack
, visit
, ram_get_gc_tags (visit
)>>5));
59 if ((HAS_1_OBJECT_FIELD (visit
) && ram_get_gc_tag0 (visit
))
60 || (HAS_2_OBJECT_FIELDS (visit
)
61 && (ram_get_gc_tags (visit
) != GC_TAG_UNMARKED
)))
62 IF_GC_TRACE(printf ("case 1\n"));
64 if (HAS_2_OBJECT_FIELDS(visit
)) { // pairs and continuations
65 IF_GC_TRACE(printf ("case 2\n"));
69 temp
= ram_get_cdr (visit
);
72 IF_GC_TRACE(printf ("case 3\n"));
73 ram_set_gc_tags (visit
, GC_TAG_1_LEFT
);
74 ram_set_cdr (visit
, stack
);
78 IF_GC_TRACE(printf ("case 4\n"));
83 if (HAS_1_OBJECT_FIELD(visit
)) {
84 IF_GC_TRACE(printf ("case 5\n"));
88 // closures have the pointer in the cdr, not in the car as others
89 if (RAM_CLOSURE(visit
))
90 temp
= ram_get_cdr (visit
);
92 temp
= ram_get_car (visit
);
95 IF_GC_TRACE(printf ("case 6\n"));
96 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
);
97 if (RAM_CLOSURE(visit
))
98 ram_set_cdr (visit
, stack
);
100 ram_set_car (visit
, stack
);
105 IF_GC_TRACE(printf ("case 7\n"));
108 IF_GC_TRACE(printf ("case 8\n"));
110 ram_set_gc_tag0 (visit
, GC_TAG_0_LEFT
);
115 IF_GC_TRACE(printf ("pop stack=%d visit=%d (tag=%d)\n", stack
, visit
, ram_get_gc_tags (visit
)>>6));
118 if (HAS_2_OBJECT_FIELDS(stack
) && ram_get_gc_tag1 (stack
)) {
119 IF_GC_TRACE(printf ("case 9\n"));
121 temp
= ram_get_cdr (stack
); /* pop through cdr */
122 ram_set_cdr (stack
, visit
);
126 ram_set_gc_tag1(visit
, GC_TAG_UNMARKED
);
127 // we unset the "1-left" bit
132 if (RAM_CLOSURE(stack
)) {
133 // closures have one object field, but it's in the cdr
134 IF_GC_TRACE(printf ("case 10\n"));
136 temp
= ram_get_cdr (stack
); /* pop through cdr */
137 ram_set_cdr (stack
, visit
);
144 IF_GC_TRACE(printf ("case 11\n"));
146 temp
= ram_get_car (stack
); /* pop through car */
147 ram_set_car (stack
, visit
);
167 obj visit
= MAX_RAM_ENCODING
;
171 while (visit
>= (MIN_RAM_ENCODING
+ ((glovars
+ 1) >> 1))) {
172 // we don't want to sweep the global variables area
173 if ((RAM_COMPOSITE(visit
)
174 && (ram_get_gc_tags (visit
) == GC_TAG_UNMARKED
)) // 2 mark bit
175 || !(ram_get_gc_tags (visit
) & GC_TAG_0_LEFT
)) { // 1 mark bit
177 if (RAM_VECTOR(visit
)) {
178 // when we sweep a vector, we also have to sweep its contents
179 obj o
= ram_get_cdr (visit
);
180 uint16 i
= ram_get_car (visit
); // number of elements
181 ram_set_car (o
, free_list_vec
);
182 ram_set_cdr (o
, (i
+ 3) >> 2); // free length, in words
184 // TODO merge free spaces
186 ram_set_car (visit
, free_list
);
190 if (RAM_COMPOSITE(visit
))
191 ram_set_gc_tags (visit
, GC_TAG_UNMARKED
);
192 else // only 1 mark bit to unset
193 ram_set_gc_tag0 (visit
, GC_TAG_UNMARKED
);
204 printf ("**************** memory needed = %d\n", max_live
+1);
213 IF_TRACE(printf("\nGC BEGINS\n"));
215 IF_GC_TRACE(printf("arg1\n"));
217 IF_GC_TRACE(printf("arg2\n"));
219 IF_GC_TRACE(printf("arg3\n"));
221 IF_GC_TRACE(printf("arg4\n"));
223 IF_GC_TRACE(printf("arg5\n"));
225 IF_GC_TRACE(printf("cont\n"));
227 IF_GC_TRACE(printf("env\n"));
230 IF_GC_TRACE(printf("globals\n"));
231 for (i
=0; i
<glovars
; i
++)
232 mark (get_global (i
));
237 obj
alloc_ram_cell (void) {
244 if (free_list
== 0) {
249 ERROR("alloc_ram_cell", "memory is full");
254 free_list
= ram_get_car (o
);
259 obj
alloc_ram_cell_init (uint8 f0
, uint8 f1
, uint8 f2
, uint8 f3
) {
260 obj o
= alloc_ram_cell ();
262 ram_set_field0 (o
, f0
);
263 ram_set_field1 (o
, f1
);
264 ram_set_field2 (o
, f2
);
265 ram_set_field3 (o
, f3
);
270 obj
alloc_vec_cell (uint16 n
) {
271 obj o
= free_list_vec
;
280 while ((ram_get_cdr (o
) * 4) < n
) { // free space too small
281 if (o
== 0) { // no free space, or none big enough
282 if (gc_done
) // we gc'd, but no space is big enough for the vector
283 ERROR("alloc_vec_cell", "no room for vector");
291 } // TODO merge adjacent free spaces, maybe compact ?
296 // case 1 : the new vector fills every free word advertized, we remove the
297 // node from the free list
298 if (((ram_get_cdr(o
) * 4) - n
) < 4) {
300 ram_set_car (prec
, ram_get_car (o
));
302 free_list_vec
= ram_get_car (o
);
304 // case 2 : there is still some space left in the free section, create a new
305 // node to represent this space
307 obj new_free
= o
+ (n
+ 3) >> 2;
309 ram_set_car (prec
, new_free
);
311 free_list_vec
= new_free
;
312 ram_set_car (new_free
, ram_get_car (o
));
313 ram_set_cdr (new_free
, ram_get_cdr (o
) - (n
+ 3) >> 2);