2 * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
3 * Copyright (c) 1991, 1992 by Xerox Corporation. All rights reserved.
5 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
6 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
8 * Permission is hereby granted to copy this garbage collector for any purpose,
9 * provided the above notices are retained on all copies.
11 # define I_HIDE_POINTERS
13 # include "gc_private.h"
15 typedef void * void_star;
17 typedef char * void_star;
21 # define TSIZE (1 << LOG_TSIZE)
23 ((((word)(addr) >> 3) ^ ((word)(addr) >> (3+LOG_TSIZE))) \
26 static struct disappearing_link {
27 word dl_hidden_base; /* Pointer to object base */
28 word dl_offset; /* byte offset within object. */
29 struct disappearing_link * dl_next;
30 } * dl_head[TSIZE] = {0};
32 static struct finalizable_object {
33 word fo_hidden_base; /* Pointer to object base */
34 GC_finalization_proc fo_fn; /* Finalizer. */
36 word fo_object_size; /* In bytes. */
37 struct finalizable_object * fo_next;
38 } * fo_head[TSIZE] = {0};
40 # define ALLOC(x, t) t *x = (t *)GC_malloc(sizeof (t))
42 int GC_register_disappearing_link(link)
47 struct disappearing_link *curr_dl;
49 /* Allocate before acquiring lock */
50 ALLOC(new_dl, struct disappearing_link);
55 base = (ptr_t)GC_base((void_star)link);
57 offset = (ptr_t)link - base;
58 if (base == 0 || ((word)link & (ALIGNMENT-1)))
59 ABORT("Bad arg to GC_register_disappearing_link");
60 curr_dl = dl_head[index];
61 for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = curr_dl -> dl_next) {
62 if (curr_dl -> dl_hidden_base == HIDE_POINTER(base)
63 && curr_dl -> dl_offset == offset) {
66 GC_free((extern_ptr_t)new_dl);
71 new_dl -> dl_hidden_base = HIDE_POINTER(base);
72 new_dl -> dl_offset = offset;
73 new_dl -> dl_next = dl_head[index];
74 dl_head[index] = new_dl;
82 int GC_unregister_disappearing_link(link)
87 struct disappearing_link *curr_dl, *prev_dl;
93 base = (ptr_t)GC_base((void_star)link);
95 offset = (ptr_t)link - base;
96 if (base == 0 || ((unsigned long)link & (ALIGNMENT-1)))
98 prev_dl = 0; curr_dl = dl_head[index];
99 while (curr_dl != 0) {
100 if (curr_dl -> dl_hidden_base == HIDE_POINTER(base)
101 && curr_dl -> dl_offset == offset) {
103 dl_head[index] = curr_dl -> dl_next;
105 prev_dl -> dl_next = curr_dl -> dl_next;
109 GC_free((extern_ptr_t)curr_dl);
112 curr_dl = curr_dl -> dl_next;
123 register struct hblk *h = HBLKPTR(p);
124 register hdr * hhdr = HDR(h);
125 register int word_no = (word *)p - (word *)h;
127 return(mark_bit_from_hdr(hhdr, word_no));
130 void GC_set_mark_bit(p)
133 register struct hblk *h = HBLKPTR(p);
134 register hdr * hhdr = HDR(h);
135 register int word_no = (word *)p - (word *)h;
137 set_mark_bit_from_hdr(hhdr, word_no);
140 void GC_clear_mark_bit(p)
143 register struct hblk *h = HBLKPTR(p);
144 register hdr * hhdr = HDR(h);
145 register int word_no = (word *)p - (word *)h;
147 clear_mark_bit_from_hdr(hhdr, word_no);
150 void GC_register_finalizer(obj, fn, cd, ofn, ocd)
152 GC_finalization_proc fn;
154 GC_finalization_proc * ofn;
158 struct finalizable_object * curr_fo, * prev_fo;
160 /* Allocate before acquiring lock */
161 ALLOC(new_fo, struct finalizable_object);
166 base = (ptr_t)GC_base((void_star)obj);
169 ABORT("Bad arg to GC_register_finalizer");
170 prev_fo = 0; curr_fo = fo_head[index];
171 while (curr_fo != 0) {
172 if (curr_fo -> fo_hidden_base == HIDE_POINTER(base)) {
173 if (ofn) *ofn = curr_fo -> fo_fn;
174 if (ocd) *ocd = (void_star) curr_fo -> fo_client_data;
176 /* Delete the structure for base. */
178 fo_head[index] = curr_fo -> fo_next;
180 prev_fo -> fo_next = curr_fo -> fo_next;
184 GC_free((extern_ptr_t)curr_fo);
186 curr_fo -> fo_fn = fn;
187 curr_fo -> fo_client_data = (ptr_t)cd;
191 GC_free((extern_ptr_t)new_fo);
194 curr_fo = curr_fo -> fo_next;
203 GC_free((extern_ptr_t)new_fo);
206 new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
207 new_fo -> fo_fn = fn;
208 new_fo -> fo_client_data = (ptr_t)cd;
209 new_fo -> fo_object_size = GC_size(base);
210 new_fo -> fo_next = fo_head[index];
211 fo_head[index] = new_fo;
217 /* Called with world stopped. Cause disappearing links to disappear, */
218 /* and invoke finalizers. */
221 struct disappearing_link * curr_dl, * prev_dl, * next_dl;
222 struct finalizable_object * curr_fo, * prev_fo, * next_fo;
226 /* Make disappearing links disappear */
227 for (i = 0; i < TSIZE; i++) {
228 curr_dl = dl_head[i];
230 while (curr_dl != 0) {
231 real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_base);
232 if (!GC_is_marked(real_ptr)) {
233 *(word *)(real_ptr + curr_dl -> dl_offset) = 0;
234 next_dl = curr_dl -> dl_next;
236 dl_head[i] = next_dl;
238 prev_dl -> dl_next = next_dl;
240 GC_clear_mark_bit((ptr_t)curr_dl);
244 curr_dl = curr_dl -> dl_next;
248 /* Mark all objects reachable via chains of 1 or more pointers */
249 /* from finalizable objects. */
250 for (i = 0; i < TSIZE; i++) {
251 for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = curr_fo -> fo_next) {
252 real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
253 if (!GC_is_marked(real_ptr)) {
254 GC_mark_all(real_ptr, real_ptr + curr_fo -> fo_object_size);
257 if (GC_is_marked(real_ptr)) {
258 --> Report finalization cycle here, if desired
263 /* Invoke finalization code for all objects that are still */
265 for (i = 0; i < TSIZE; i++) {
266 curr_fo = fo_head[i];
268 while (curr_fo != 0) {
269 real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
270 if (!GC_is_marked(real_ptr)) {
271 (*(curr_fo -> fo_fn))(real_ptr, curr_fo -> fo_client_data);
272 GC_set_mark_bit(real_ptr);
273 next_fo = curr_fo -> fo_next;
275 fo_head[i] = next_fo;
277 prev_fo -> fo_next = next_fo;
279 if (!GC_is_marked((ptr_t)curr_fo)) {
280 ABORT("GC_finalize: found accessible unmarked object\n");
282 GC_clear_mark_bit((ptr_t)curr_fo);
286 curr_fo = curr_fo -> fo_next;
293 void_star GC_call_with_alloc_lock(GC_fn_type fn, void_star client_data)
295 void_star GC_call_with_alloc_lock(fn, client_data)
297 void_star client_data;