3 CELL
init_zone(F_ZONE
*z
, CELL size
, CELL start
)
6 z
->start
= z
->here
= start
;
11 void init_card_decks(void)
13 CELL start
= align(data_heap
->segment
->start
,DECK_SIZE
);
14 allot_markers_offset
= (CELL
)data_heap
->allot_markers
- (start
>> CARD_BITS
);
15 cards_offset
= (CELL
)data_heap
->cards
- (start
>> CARD_BITS
);
16 decks_offset
= (CELL
)data_heap
->decks
- (start
>> DECK_BITS
);
19 F_DATA_HEAP
*alloc_data_heap(CELL gens
,
24 young_size
= align(young_size
,DECK_SIZE
);
25 aging_size
= align(aging_size
,DECK_SIZE
);
26 tenured_size
= align(tenured_size
,DECK_SIZE
);
28 F_DATA_HEAP
*data_heap
= safe_malloc(sizeof(F_DATA_HEAP
));
29 data_heap
->young_size
= young_size
;
30 data_heap
->aging_size
= aging_size
;
31 data_heap
->tenured_size
= tenured_size
;
32 data_heap
->gen_count
= gens
;
35 if(data_heap
->gen_count
== 2)
36 total_size
= young_size
+ 2 * tenured_size
;
37 else if(data_heap
->gen_count
== 3)
38 total_size
= young_size
+ 2 * aging_size
+ 2 * tenured_size
;
41 fatal_error("Invalid number of generations",data_heap
->gen_count
);
42 return NULL
; /* can't happen */
45 total_size
+= DECK_SIZE
;
47 data_heap
->segment
= alloc_segment(total_size
);
49 data_heap
->generations
= safe_malloc(sizeof(F_ZONE
) * data_heap
->gen_count
);
50 data_heap
->semispaces
= safe_malloc(sizeof(F_ZONE
) * data_heap
->gen_count
);
52 CELL cards_size
= total_size
>> CARD_BITS
;
53 data_heap
->allot_markers
= safe_malloc(cards_size
);
54 data_heap
->allot_markers_end
= data_heap
->allot_markers
+ cards_size
;
56 data_heap
->cards
= safe_malloc(cards_size
);
57 data_heap
->cards_end
= data_heap
->cards
+ cards_size
;
59 CELL decks_size
= total_size
>> DECK_BITS
;
60 data_heap
->decks
= safe_malloc(decks_size
);
61 data_heap
->decks_end
= data_heap
->decks
+ decks_size
;
63 CELL alloter
= align(data_heap
->segment
->start
,DECK_SIZE
);
65 alloter
= init_zone(&data_heap
->generations
[TENURED
],tenured_size
,alloter
);
66 alloter
= init_zone(&data_heap
->semispaces
[TENURED
],tenured_size
,alloter
);
68 if(data_heap
->gen_count
== 3)
70 alloter
= init_zone(&data_heap
->generations
[AGING
],aging_size
,alloter
);
71 alloter
= init_zone(&data_heap
->semispaces
[AGING
],aging_size
,alloter
);
74 if(data_heap
->gen_count
>= 2)
76 alloter
= init_zone(&data_heap
->generations
[NURSERY
],young_size
,alloter
);
77 alloter
= init_zone(&data_heap
->semispaces
[NURSERY
],0,alloter
);
80 if(data_heap
->segment
->end
- alloter
> DECK_SIZE
)
81 critical_error("Bug in alloc_data_heap",alloter
);
86 F_DATA_HEAP
*grow_data_heap(F_DATA_HEAP
*data_heap
, CELL requested_bytes
)
88 CELL new_tenured_size
= (data_heap
->tenured_size
* 2) + requested_bytes
;
90 return alloc_data_heap(data_heap
->gen_count
,
91 data_heap
->young_size
,
92 data_heap
->aging_size
,
96 void dealloc_data_heap(F_DATA_HEAP
*data_heap
)
98 dealloc_segment(data_heap
->segment
);
99 free(data_heap
->generations
);
100 free(data_heap
->semispaces
);
101 free(data_heap
->allot_markers
);
102 free(data_heap
->cards
);
103 free(data_heap
->decks
);
107 void clear_cards(CELL from
, CELL to
)
109 /* NOTE: reverse order due to heap layout. */
110 F_CARD
*first_card
= ADDR_TO_CARD(data_heap
->generations
[to
].start
);
111 F_CARD
*last_card
= ADDR_TO_CARD(data_heap
->generations
[from
].end
);
112 memset(first_card
,0,last_card
- first_card
);
115 void clear_decks(CELL from
, CELL to
)
117 /* NOTE: reverse order due to heap layout. */
118 F_DECK
*first_deck
= ADDR_TO_DECK(data_heap
->generations
[to
].start
);
119 F_DECK
*last_deck
= ADDR_TO_DECK(data_heap
->generations
[from
].end
);
120 memset(first_deck
,0,last_deck
- first_deck
);
123 void clear_allot_markers(CELL from
, CELL to
)
125 /* NOTE: reverse order due to heap layout. */
126 F_CARD
*first_card
= ADDR_TO_ALLOT_MARKER(data_heap
->generations
[to
].start
);
127 F_CARD
*last_card
= ADDR_TO_ALLOT_MARKER(data_heap
->generations
[from
].end
);
128 memset(first_card
,INVALID_ALLOT_MARKER
,last_card
- first_card
);
131 void reset_generation(CELL i
)
133 F_ZONE
*z
= (i
== NURSERY
? &nursery
: &data_heap
->generations
[i
]);
137 memset((void*)z
->start
,69,z
->size
);
140 /* After garbage collection, any generations which are now empty need to have
141 their allocation pointers and cards reset. */
142 void reset_generations(CELL from
, CELL to
)
145 for(i
= from
; i
<= to
; i
++)
148 clear_cards(from
,to
);
149 clear_decks(from
,to
);
150 clear_allot_markers(from
,to
);
153 void set_data_heap(F_DATA_HEAP
*data_heap_
)
155 data_heap
= data_heap_
;
156 nursery
= data_heap
->generations
[NURSERY
];
158 clear_cards(NURSERY
,TENURED
);
159 clear_decks(NURSERY
,TENURED
);
160 clear_allot_markers(NURSERY
,TENURED
);
163 void init_data_heap(CELL gens
,
169 set_data_heap(alloc_data_heap(gens
,young_size
,aging_size
,tenured_size
));
171 gc_locals_region
= alloc_segment(getpagesize());
172 gc_locals
= gc_locals_region
->start
- CELLS
;
174 extra_roots_region
= alloc_segment(getpagesize());
175 extra_roots
= extra_roots_region
->start
- CELLS
;
177 secure_gc
= secure_gc_
;
180 /* Size of the object pointed to by a tagged pointer */
181 CELL
object_size(CELL tagged
)
183 if(immediate_p(tagged
))
186 return untagged_object_size(UNTAG(tagged
));
189 /* Size of the object pointed to by an untagged pointer */
190 CELL
untagged_object_size(CELL pointer
)
192 return align8(unaligned_object_size(pointer
));
195 /* Size of the data area of an object pointed to by an untagged pointer */
196 CELL
unaligned_object_size(CELL pointer
)
199 F_TUPLE_LAYOUT
*layout
;
201 switch(untag_header(get(pointer
)))
205 return array_size(array_capacity((F_ARRAY
*)pointer
));
206 case BYTE_ARRAY_TYPE
:
207 return byte_array_size(
208 byte_array_capacity((F_BYTE_ARRAY
*)pointer
));
210 return string_size(string_capacity((F_STRING
*)pointer
));
212 tuple
= untag_object(pointer
);
213 layout
= untag_object(tuple
->layout
);
214 return tuple_size(layout
);
216 return sizeof(F_QUOTATION
);
218 return sizeof(F_WORD
);
220 return sizeof(F_RATIO
);
222 return sizeof(F_FLOAT
);
224 return sizeof(F_COMPLEX
);
226 return sizeof(F_DLL
);
228 return sizeof(F_ALIEN
);
230 return sizeof(F_WRAPPER
);
232 return callstack_size(
233 untag_fixnum_fast(((F_CALLSTACK
*)pointer
)->length
));
235 critical_error("Invalid header",pointer
);
236 return -1; /* can't happen */
240 void primitive_size(void)
242 box_unsigned_cell(object_size(dpop()));
245 /* The number of cells from the start of the object which should be scanned by
246 the GC. Some types have a binary payload at the end (string, word, DLL) which
248 CELL
binary_payload_start(CELL pointer
)
251 F_TUPLE_LAYOUT
*layout
;
253 switch(untag_header(get(pointer
)))
255 /* these objects do not refer to other objects at all */
257 case BYTE_ARRAY_TYPE
:
261 /* these objects have some binary data at the end */
263 return sizeof(F_WORD
) - CELLS
* 3;
269 return sizeof(F_QUOTATION
) - CELLS
* 2;
271 return sizeof(F_STRING
);
272 /* everything else consists entirely of pointers */
274 return array_size(array_capacity((F_ARRAY
*)pointer
));
276 tuple
= untag_object(pointer
);
277 layout
= untag_object(tuple
->layout
);
278 return tuple_size(layout
);
280 return sizeof(F_RATIO
);
282 return sizeof(F_COMPLEX
);
284 return sizeof(F_WRAPPER
);
286 critical_error("Invalid header",pointer
);
287 return -1; /* can't happen */
291 /* Push memory usage statistics in data heap */
292 void primitive_data_room(void)
294 F_ARRAY
*a
= allot_array(ARRAY_TYPE
,data_heap
->gen_count
* 2,F
);
297 dpush(tag_fixnum((data_heap
->cards_end
- data_heap
->cards
) >> 10));
298 dpush(tag_fixnum((data_heap
->decks_end
- data_heap
->decks
) >> 10));
300 for(gen
= 0; gen
< data_heap
->gen_count
; gen
++)
302 F_ZONE
*z
= (gen
== NURSERY
? &nursery
: &data_heap
->generations
[gen
]);
303 set_array_nth(a
,gen
* 2,tag_fixnum((z
->end
- z
->here
) >> 10));
304 set_array_nth(a
,gen
* 2 + 1,tag_fixnum((z
->size
) >> 10));
307 dpush(tag_object(a
));
310 /* Disables GC and activates next-object ( -- obj ) primitive */
311 void begin_scan(void)
313 heap_scan_ptr
= data_heap
->generations
[TENURED
].start
;
317 void primitive_begin_scan(void)
322 CELL
next_object(void)
325 general_error(ERROR_HEAP_SCAN
,F
,F
,NULL
);
327 CELL value
= get(heap_scan_ptr
);
328 CELL obj
= heap_scan_ptr
;
331 if(heap_scan_ptr
>= data_heap
->generations
[TENURED
].here
)
334 type
= untag_header(value
);
335 heap_scan_ptr
+= untagged_object_size(heap_scan_ptr
);
337 return RETAG(obj
,type
<= HEADER_TYPE
? type
: OBJECT_TYPE
);
340 /* Push object at heap scan cursor and advance; pushes f when done */
341 void primitive_next_object(void)
343 dpush(next_object());
347 void primitive_end_scan(void)
352 CELL
find_all_words(void)
354 GROWABLE_ARRAY(words
);
359 while((obj
= next_object()) != F
)
361 if(type_of(obj
) == WORD_TYPE
)
362 GROWABLE_ARRAY_ADD(words
,obj
);
368 GROWABLE_ARRAY_TRIM(words
);