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_obj; /* Pointer to object base */
28 word dl_hidden_link; /* Field to be cleared. */
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};
41 void GC_push_finalizer_structures()
43 GC_push_all((ptr_t)dl_head, (ptr_t)(dl_head + TSIZE));
44 GC_push_all((ptr_t)fo_head, (ptr_t)(fo_head + TSIZE));
48 # define ALLOC(x, t) t *x = (t *)GC_malloc(sizeof (t))
50 int GC_register_disappearing_link(link)
55 base = (ptr_t)GC_base((void_star)link);
57 ABORT("Bad arg to GC_register_disappearing_link");
58 return(GC_general_register_disappearing_link(link, base));
61 int GC_general_register_disappearing_link(link, obj)
65 struct disappearing_link *curr_dl;
67 /* Allocate before acquiring lock */
68 ALLOC(new_dl, struct disappearing_link);
72 if ((word)link & (ALIGNMENT-1))
73 ABORT("Bad arg to GC_general_register_disappearing_link");
76 curr_dl = dl_head[index];
77 for (curr_dl = dl_head[index]; curr_dl != 0; curr_dl = curr_dl -> dl_next) {
78 if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
79 curr_dl -> dl_hidden_obj = HIDE_POINTER(obj);
82 GC_free((extern_ptr_t)new_dl);
87 new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
88 new_dl -> dl_hidden_link = HIDE_POINTER(link);
89 new_dl -> dl_next = dl_head[index];
90 dl_head[index] = new_dl;
97 int GC_unregister_disappearing_link(link)
100 struct disappearing_link *curr_dl, *prev_dl;
105 if (((unsigned long)link & (ALIGNMENT-1)))
109 prev_dl = 0; curr_dl = dl_head[index];
110 while (curr_dl != 0) {
111 if (curr_dl -> dl_hidden_link == HIDE_POINTER(link)) {
113 dl_head[index] = curr_dl -> dl_next;
115 prev_dl -> dl_next = curr_dl -> dl_next;
119 GC_free((extern_ptr_t)curr_dl);
123 curr_dl = curr_dl -> dl_next;
130 void GC_register_finalizer(obj, fn, cd, ofn, ocd)
132 GC_finalization_proc fn;
134 GC_finalization_proc * ofn;
138 struct finalizable_object * curr_fo, * prev_fo;
140 /* Allocate before acquiring lock */
141 ALLOC(new_fo, struct finalizable_object);
146 base = (ptr_t)GC_base((void_star)obj);
149 ABORT("Bad arg to GC_register_finalizer");
150 prev_fo = 0; curr_fo = fo_head[index];
151 while (curr_fo != 0) {
152 if (curr_fo -> fo_hidden_base == HIDE_POINTER(base)) {
153 if (ofn) *ofn = curr_fo -> fo_fn;
154 if (ocd) *ocd = (void_star) curr_fo -> fo_client_data;
156 /* Delete the structure for base. */
158 fo_head[index] = curr_fo -> fo_next;
160 prev_fo -> fo_next = curr_fo -> fo_next;
164 GC_free((extern_ptr_t)curr_fo);
166 curr_fo -> fo_fn = fn;
167 curr_fo -> fo_client_data = (ptr_t)cd;
171 GC_free((extern_ptr_t)new_fo);
175 curr_fo = curr_fo -> fo_next;
183 GC_free((extern_ptr_t)new_fo);
186 new_fo -> fo_hidden_base = (word)HIDE_POINTER(base);
187 new_fo -> fo_fn = fn;
188 new_fo -> fo_client_data = (ptr_t)cd;
189 new_fo -> fo_object_size = GC_size(base);
190 new_fo -> fo_next = fo_head[index];
191 fo_head[index] = new_fo;
197 /* Called with world stopped. Cause disappearing links to disappear, */
198 /* and invoke finalizers. */
201 struct disappearing_link * curr_dl, * prev_dl, * next_dl;
202 struct finalizable_object * curr_fo, * prev_fo, * next_fo;
206 /* Make disappearing links disappear */
207 for (i = 0; i < TSIZE; i++) {
208 curr_dl = dl_head[i];
210 while (curr_dl != 0) {
211 real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
212 if (!GC_is_marked(real_ptr)) {
213 *(word *)(REVEAL_POINTER(curr_dl -> dl_hidden_link)) = 0;
214 next_dl = curr_dl -> dl_next;
216 dl_head[i] = next_dl;
218 prev_dl -> dl_next = next_dl;
220 GC_clear_mark_bit((ptr_t)curr_dl);
224 curr_dl = curr_dl -> dl_next;
228 /* Mark all objects reachable via chains of 1 or more pointers */
229 /* from finalizable objects. */
230 for (i = 0; i < TSIZE; i++) {
231 for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = curr_fo -> fo_next) {
232 real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
233 if (!GC_is_marked(real_ptr)) {
234 GC_push_all(real_ptr, real_ptr + curr_fo -> fo_object_size);
235 while (!GC_mark_stack_empty()) GC_mark_from_mark_stack();
238 if (GC_is_marked(real_ptr)) {
239 --> Report finalization cycle here, if desired
244 /* Invoke finalization code for all objects that are still */
246 for (i = 0; i < TSIZE; i++) {
247 curr_fo = fo_head[i];
249 while (curr_fo != 0) {
250 real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base);
251 if (!GC_is_marked(real_ptr)) {
252 (*(curr_fo -> fo_fn))(real_ptr, curr_fo -> fo_client_data);
253 GC_set_mark_bit(real_ptr);
254 next_fo = curr_fo -> fo_next;
256 fo_head[i] = next_fo;
258 prev_fo -> fo_next = next_fo;
260 if (!GC_is_marked((ptr_t)curr_fo)) {
261 ABORT("GC_finalize: found accessible unmarked object\n");
263 GC_clear_mark_bit((ptr_t)curr_fo);
267 curr_fo = curr_fo -> fo_next;
274 void_star GC_call_with_alloc_lock(GC_fn_type fn, void_star client_data)
276 void_star GC_call_with_alloc_lock(fn, client_data)
278 void_star client_data;
286 result = (*fn)(client_data);