STATIC struct dl_hashtbl_s GC_ll_hashtbl = { NULL, -1, 0 };
#endif
-STATIC struct finalizable_object {
+struct finalizable_object {
struct hash_chain_entry prolog;
# define fo_hidden_base prolog.hidden_key
/* Pointer to object base. */
ptr_t fo_client_data;
word fo_object_size; /* In bytes. */
finalization_mark_proc fo_mark_proc; /* Mark-through procedure */
-} **GC_fo_head = 0;
-
-STATIC struct finalizable_object * GC_finalize_now = 0;
- /* List of objects that should be finalized now. */
+};
static signed_word log_fo_table_size = -1;
+STATIC struct {
+ struct finalizable_object **fo_head;
+ /* List of objects that should be finalized now: */
+ struct finalizable_object *finalize_now;
+} GC_fnlz_roots = { NULL, NULL };
+
GC_API void GC_CALL GC_push_finalizer_structures(void)
{
GC_ASSERT((word)&GC_dl_hashtbl.head % sizeof(word) == 0);
- GC_ASSERT((word)&GC_fo_head % sizeof(word) == 0);
- GC_ASSERT((word)&GC_finalize_now % sizeof(word) == 0);
+ GC_ASSERT((word)&GC_fnlz_roots % sizeof(word) == 0);
# ifndef GC_LONG_REFS_NOT_NEEDED
GC_ASSERT((word)&GC_ll_hashtbl.head % sizeof(word) == 0);
GC_PUSH_ALL_SYM(GC_ll_hashtbl.head);
# endif
GC_PUSH_ALL_SYM(GC_dl_hashtbl.head);
- GC_PUSH_ALL_SYM(GC_fo_head);
- GC_PUSH_ALL_SYM(GC_finalize_now);
+ GC_PUSH_ALL_SYM(GC_fnlz_roots);
}
/* Double the size of a hash table. *size_ptr is the log of its current */
LOCK();
if (log_fo_table_size == -1
|| GC_fo_entries > ((word)1 << log_fo_table_size)) {
- GC_grow_table((struct hash_chain_entry ***)&GC_fo_head,
+ GC_grow_table((struct hash_chain_entry ***)&GC_fnlz_roots.fo_head,
&log_fo_table_size);
GC_COND_LOG_PRINTF("Grew fo table to %u entries\n",
1 << (unsigned)log_fo_table_size);
for (;;) {
index = HASH2(base, log_fo_table_size);
prev_fo = 0;
- curr_fo = GC_fo_head[index];
+ curr_fo = GC_fnlz_roots.fo_head[index];
while (curr_fo != 0) {
GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));
if (curr_fo -> fo_hidden_base == GC_HIDE_POINTER(base)) {
if (ofn) *ofn = curr_fo -> fo_fn;
/* Delete the structure for base. */
if (prev_fo == 0) {
- GC_fo_head[index] = fo_next(curr_fo);
+ GC_fnlz_roots.fo_head[index] = fo_next(curr_fo);
} else {
fo_set_next(prev_fo, fo_next(curr_fo));
}
/* Reinsert it. We deleted it first to maintain */
/* consistency in the event of a signal. */
if (prev_fo == 0) {
- GC_fo_head[index] = curr_fo;
+ GC_fnlz_roots.fo_head[index] = curr_fo;
} else {
fo_set_next(prev_fo, curr_fo);
}
new_fo -> fo_client_data = (ptr_t)cd;
new_fo -> fo_object_size = hhdr -> hb_sz;
new_fo -> fo_mark_proc = mp;
- fo_set_next(new_fo, GC_fo_head[index]);
+ fo_set_next(new_fo, GC_fnlz_roots.fo_head[index]);
GC_fo_entries++;
- GC_fo_head[index] = new_fo;
+ GC_fnlz_roots.fo_head[index] = new_fo;
UNLOCK();
}
# endif
GC_printf("Finalizers:\n");
for (i = 0; i < fo_size; i++) {
- for (curr_fo = GC_fo_head[i]; curr_fo != 0;
- curr_fo = fo_next(curr_fo)) {
+ for (curr_fo = GC_fnlz_roots.fo_head[i];
+ curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base);
GC_printf("Finalizable object: %p\n", real_ptr);
}
/* from finalizable objects. */
GC_ASSERT(GC_mark_state == MS_NONE);
for (i = 0; i < fo_size; i++) {
- for (curr_fo = GC_fo_head[i]; curr_fo != 0;
- curr_fo = fo_next(curr_fo)) {
+ for (curr_fo = GC_fnlz_roots.fo_head[i];
+ curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
GC_ASSERT(GC_size(curr_fo) >= sizeof(struct finalizable_object));
real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base);
if (!GC_is_marked(real_ptr)) {
/* unreachable. */
GC_bytes_finalized = 0;
for (i = 0; i < fo_size; i++) {
- curr_fo = GC_fo_head[i];
+ curr_fo = GC_fnlz_roots.fo_head[i];
prev_fo = 0;
while (curr_fo != 0) {
real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base);
}
/* Delete from hash table */
next_fo = fo_next(curr_fo);
- if (prev_fo == 0) {
- GC_fo_head[i] = next_fo;
+ if (NULL == prev_fo) {
+ GC_fnlz_roots.fo_head[i] = next_fo;
} else {
fo_set_next(prev_fo, next_fo);
}
GC_object_finalized_proc(real_ptr);
/* Add to list of objects awaiting finalization. */
- fo_set_next(curr_fo, GC_finalize_now);
- GC_finalize_now = curr_fo;
+ fo_set_next(curr_fo, GC_fnlz_roots.finalize_now);
+ GC_fnlz_roots.finalize_now = curr_fo;
/* unhide object pointer so any future collections will */
/* see it. */
curr_fo -> fo_hidden_base =
if (GC_java_finalization) {
/* make sure we mark everything reachable from objects finalized
using the no_order mark_proc */
- for (curr_fo = GC_finalize_now;
- curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
+ for (curr_fo = GC_fnlz_roots.finalize_now;
+ curr_fo != NULL; curr_fo = fo_next(curr_fo)) {
real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
if (!GC_is_marked(real_ptr)) {
if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
/* now revive finalize-when-unreachable objects reachable from
other finalizable objects */
if (need_unreachable_finalization) {
- curr_fo = GC_finalize_now;
- prev_fo = 0;
- while (curr_fo != 0) {
+ curr_fo = GC_fnlz_roots.finalize_now;
+ prev_fo = NULL;
+ while (curr_fo != NULL) {
next_fo = fo_next(curr_fo);
if (curr_fo -> fo_mark_proc == GC_unreachable_finalize_mark_proc) {
real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
if (!GC_is_marked(real_ptr)) {
GC_set_mark_bit(real_ptr);
} else {
- if (prev_fo == 0)
- GC_finalize_now = next_fo;
- else
+ if (NULL == prev_fo) {
+ GC_fnlz_roots.finalize_now = next_fo;
+ } else {
fo_set_next(prev_fo, next_fo);
-
+ }
curr_fo -> fo_hidden_base =
GC_HIDE_POINTER(curr_fo -> fo_hidden_base);
GC_bytes_finalized -=
curr_fo->fo_object_size + sizeof(struct finalizable_object);
i = HASH2(real_ptr, log_fo_table_size);
- fo_set_next (curr_fo, GC_fo_head[i]);
+ fo_set_next(curr_fo, GC_fnlz_roots.fo_head[i]);
GC_fo_entries++;
- GC_fo_head[i] = curr_fo;
+ GC_fnlz_roots.fo_head[i] = curr_fo;
curr_fo = prev_fo;
}
}
fo_size = log_fo_table_size == -1 ? 0 : 1 << log_fo_table_size;
GC_bytes_finalized = 0;
for (i = 0; i < fo_size; i++) {
- curr_fo = GC_fo_head[i];
- prev_fo = 0;
- while (curr_fo != 0) {
+ curr_fo = GC_fnlz_roots.fo_head[i];
+ prev_fo = NULL;
+ while (curr_fo != NULL) {
real_ptr = GC_REVEAL_POINTER(curr_fo -> fo_hidden_base);
GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
GC_set_mark_bit(real_ptr);
/* Delete from hash table */
next_fo = fo_next(curr_fo);
if (prev_fo == 0) {
- GC_fo_head[i] = next_fo;
+ GC_fnlz_roots.fo_head[i] = next_fo;
} else {
- fo_set_next(prev_fo, next_fo);
+ fo_set_next(prev_fo, next_fo);
}
GC_fo_entries--;
/* Add to list of objects awaiting finalization. */
- fo_set_next(curr_fo, GC_finalize_now);
- GC_finalize_now = curr_fo;
+ fo_set_next(curr_fo, GC_fnlz_roots.finalize_now);
+ GC_fnlz_roots.finalize_now = curr_fo;
/* unhide object pointer so any future collections will */
/* see it. */
/* getting into that safe state is expensive.) */
GC_API int GC_CALL GC_should_invoke_finalizers(void)
{
- return GC_finalize_now != 0;
+ return GC_fnlz_roots.finalize_now != NULL;
}
/* Invoke finalizers for all objects that are ready to be finalized. */
word bytes_freed_before = 0; /* initialized to prevent warning. */
DCL_LOCK_STATE;
- while (GC_finalize_now != 0) {
+ while (GC_fnlz_roots.finalize_now != NULL) {
# ifdef THREADS
LOCK();
# endif
bytes_freed_before = GC_bytes_freed;
/* Don't do this outside, since we need the lock. */
}
- curr_fo = GC_finalize_now;
+ curr_fo = GC_fnlz_roots.finalize_now;
# ifdef THREADS
- if (curr_fo != 0) GC_finalize_now = fo_next(curr_fo);
+ if (curr_fo != 0) GC_fnlz_roots.finalize_now = fo_next(curr_fo);
UNLOCK();
if (curr_fo == 0) break;
# else
- GC_finalize_now = fo_next(curr_fo);
+ GC_fnlz_roots.finalize_now = fo_next(curr_fo);
# endif
fo_set_next(curr_fo, 0);
(*(curr_fo -> fo_fn))((ptr_t)(curr_fo -> fo_hidden_base),
# if defined(THREADS) && !defined(KEEP_BACK_PTRS) \
&& !defined(MAKE_BACK_GRAPH)
/* Quick check (while unlocked) for an empty finalization queue. */
- if (GC_finalize_now == 0) return;
+ if (NULL == GC_fnlz_roots.finalize_now) return;
# endif
LOCK();
# endif
}
# endif
- if (GC_finalize_now == 0) {
+ if (NULL == GC_fnlz_roots.finalize_now) {
UNLOCK();
return;
}
(void) GC_invoke_finalizers();
*pnested = 0; /* Reset since no more finalizers. */
# ifndef THREADS
- GC_ASSERT(GC_finalize_now == 0);
+ GC_ASSERT(NULL == GC_fnlz_roots.finalize_now);
# endif /* Otherwise GC can run concurrently and add more */
}
return;
(unsigned long)IF_LONG_REFS_PRESENT_ELSE(
GC_ll_hashtbl.entries, 0));
- for (fo = GC_finalize_now; 0 != fo; fo = fo_next(fo))
+ for (fo = GC_fnlz_roots.finalize_now; fo != NULL; fo = fo_next(fo))
++ready;
GC_log_printf("%lu finalization-ready objects;"
" %ld/%ld short/long links cleared\n",