* doc/README.macros (GC_NO_FINALIZATION): Document.
* alloc.c (GC_finish_collection): Do not call GC_finalize and
GC_print_finalization_stats if GC_NO_FINALIZATION.
* dbg_mlc.c (closure, GC_make_closure, GC_debug_invoke_finalizer,
OFN_UNSET, store_old, GC_debug_register_finalizer,
GC_debug_register_finalizer_no_order,
GC_debug_register_finalizer_unreachable,
GC_debug_register_finalizer_ignore_self): Do not define if
GC_NO_FINALIZATION.
* finalize.c: Skip all definitions if GC_NO_FINALIZATION.
* finalize.c (GC_call_with_alloc_lock): Move to misc.c.
* include/private/gc_priv.h (GC_INVOKE_FINALIZERS): Define to empty
if GC_NO_FINALIZATION.
* include/private/gc_priv.h (GC_notify_or_invoke_finalizers,
GC_push_finalizer_structures, GC_finalize,
GC_print_finalization_stats): Do not declare if GC_NO_FINALIZATION.
* mark_rts.c (GC_push_gc_structures): Do not call
GC_push_finalizer_structures if GC_NO_FINALIZATION.
* misc.c (GC_call_with_alloc_lock): Move from "finalize" module.
* tests/test.c (mktree): Do not declare "my_index" and "new_link"
local variables, do not update live_indicators_count, do not call
GC_REGISTER_FINALIZER, GC_GENERAL_REGISTER_DISAPPEARING_LINK,
GC_move_disappearing_link, GC_unregister_disappearing_link if
GC_NO_FINALIZATION.
* tests/test.c (check_heap_stats): Do not declare "still_live",
"late_finalize_count" local variables and do not check finalization
for failures if GC_NO_FINALIZATION.
/* The above just checks; it doesn't really reclaim anything. */
}
- GC_finalize();
+# ifndef GC_NO_FINALIZATION
+ GC_finalize();
+# endif
# ifdef STUBBORN_ALLOC
GC_clean_changing_list();
# endif
GET_TIME(done_time);
/* A convenient place to output finalization statistics. */
- GC_print_finalization_stats();
+# ifndef GC_NO_FINALIZATION
+ GC_print_finalization_stats();
+# endif
GC_log_printf("Finalize plus initiate sweep took %lu + %lu msecs\n",
MS_TIME_DIFF(finalize_time,start_time),
#endif /* !SHORT_DBG_HDRS */
+#ifndef GC_NO_FINALIZATION
+
struct closure {
GC_finalization_proc cl_fn;
void * cl_data;
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
+#endif /* !GC_NO_FINALIZATION */
+
GC_API void * GC_CALL GC_debug_malloc_replacement(size_t lb)
{
return GC_debug_malloc(lb, GC_DBG_RA "unknown", 0);
In 5.0 this became runtime adjustable, and this only determines the
initial value of GC_finalize_on_demand.
+GC_NO_FINALIZATION Exclude finalization support (for smaller code size)
+
ATOMIC_UNCOLLECTABLE Includes code for GC_malloc_atomic_uncollectable.
This is useful if either the vendor malloc implementation is poor,
or if REDIRECT_MALLOC is used.
#include "private/gc_pmark.h"
+#ifndef GC_NO_FINALIZATION
+
/* Type of mark procedure used for marking from finalizable object. */
/* This procedure normally does not mark the object, only its */
/* descendents. */
(*notifier_fn)(); /* Invoke the notifier */
}
-GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type fn,
- void * client_data)
-{
- void * result;
- DCL_LOCK_STATE;
-
-# ifdef THREADS
- LOCK();
- /* FIXME - This looks wrong!! */
- SET_LOCK_HOLDER();
-# endif
- result = (*fn)(client_data);
-# ifdef THREADS
-# ifndef GC_ASSERTIONS
- UNSET_LOCK_HOLDER();
-# endif /* o.w. UNLOCK() does it implicitly */
- UNLOCK();
-# endif
- return(result);
-}
-
#ifndef SMALL_CONFIG
GC_INNER void GC_print_finalization_stats(void)
{
ready, (long)GC_old_dl_entries - (long)GC_dl_entries);
}
#endif /* !SMALL_CONFIG */
+
+#endif /* !GC_NO_FINALIZATION */
/* through GC_all_interior_pointers. */
-#define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers()
+#ifndef GC_NO_FINALIZATION
+# define GC_INVOKE_FINALIZERS() GC_notify_or_invoke_finalizers()
+ GC_INNER void GC_notify_or_invoke_finalizers(void);
+ /* If GC_finalize_on_demand is not set, invoke */
+ /* eligible finalizers. Otherwise: */
+ /* Call *GC_finalizer_notifier if there are */
+ /* finalizers to be run, and we haven't called */
+ /* this procedure yet this GC cycle. */
+
+ GC_INNER void GC_push_finalizer_structures(void);
+ GC_INNER void GC_finalize(void);
+ /* Perform all indicated finalization actions */
+ /* on unmarked objects. */
+ /* Unreachable finalizable objects are enqueued */
+ /* for processing by GC_invoke_finalizers. */
+ /* Invoked with lock. */
+
+# ifndef SMALL_CONFIG
+ GC_INNER void GC_print_finalization_stats(void);
+# endif
+#else
+# define GC_INVOKE_FINALIZERS() (void)0
+#endif /* GC_NO_FINALIZATION */
#if !defined(DONT_ADD_BYTE_AT_END)
# ifdef LINT2
/* supplied replacement should also call the */
/* original function. */
-GC_INNER void GC_push_finalizer_structures(void);
#ifdef THREADS
void GC_push_thread_structures(void);
#endif
/* Remove forwarding counts for h. */
GC_INNER hdr * GC_find_header(ptr_t h);
-GC_INNER void GC_finalize(void);
- /* Perform all indicated finalization actions */
- /* on unmarked objects. */
- /* Unreachable finalizable objects are enqueued */
- /* for processing by GC_invoke_finalizers. */
- /* Invoked with lock. */
-
-GC_INNER void GC_notify_or_invoke_finalizers(void);
- /* If GC_finalize_on_demand is not set, invoke */
- /* eligible finalizers. Otherwise: */
- /* Call *GC_finalizer_notifier if there are */
- /* finalizers to be run, and we haven't called */
- /* this procedure yet this GC cycle. */
-
GC_INNER void GC_add_to_heap(struct hblk *p, size_t bytes);
/* Add a HBLKSIZE aligned chunk to the heap. */
void GC_print_hblkfreelist(void);
void GC_print_heap_sects(void);
void GC_print_static_roots(void);
-#ifndef SMALL_CONFIG
- GC_INNER void GC_print_finalization_stats(void);
-#endif
/* void GC_dump(void); - declared in gc.h */
extern word GC_fo_entries; /* should be visible in extra/MacOS.c */
*/
STATIC void GC_push_gc_structures(void)
{
- GC_push_finalizer_structures();
+# ifndef GC_NO_FINALIZATION
+ GC_push_finalizer_structures();
+# endif
# if defined(THREADS)
GC_push_thread_structures();
# endif
return result;
}
+GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type fn, void *client_data)
+{
+ void * result;
+ DCL_LOCK_STATE;
+
+# ifdef THREADS
+ LOCK();
+ /* FIXME - This looks wrong!! */
+ SET_LOCK_HOLDER();
+# endif
+ result = (*fn)(client_data);
+# ifdef THREADS
+# ifndef GC_ASSERTIONS
+ UNSET_LOCK_HOLDER();
+# endif /* o.w. UNLOCK() does it implicitly */
+ UNLOCK();
+# endif
+ return(result);
+}
+
GC_API void * GC_CALL GC_call_with_stack_base(GC_stack_base_func fn, void *arg)
{
int dummy;
result -> rchild -> lchild = tmp;
}
if (counter++ % 119 == 0) {
- int my_index;
- void *new_link;
+# ifndef GC_NO_FINALIZATION
+ int my_index;
+ void *new_link;
+# endif
{
# ifdef PCR
# endif
/* Losing a count here causes erroneous report of failure. */
finalizable_count++;
- my_index = live_indicators_count++;
+# ifndef GC_NO_FINALIZATION
+ my_index = live_indicators_count++;
+# endif
# ifdef PCR
PCR_ThCrSec_ExitSys();
# endif
# endif
}
+# ifndef GC_NO_FINALIZATION
GC_REGISTER_FINALIZER((void *)result, finalizer, (void *)(GC_word)n,
(GC_finalization_proc *)0, (void * *)0);
if (my_index >= MAX_FINALIZED) {
GC_printf("GC_general_register_disappearing_link failed 2\n");
FAIL;
}
+# endif
GC_reachable_here(result);
}
return(result);
{
size_t max_heap_sz;
int i;
- int still_live;
-# ifdef FINALIZE_ON_DEMAND
+# ifndef GC_NO_FINALIZATION
+ int still_live;
+# ifdef FINALIZE_ON_DEMAND
int late_finalize_count = 0;
+# endif
# endif
# ifdef VERY_SMALL_CONFIG
while (GC_collect_a_little()) { }
for (i = 0; i < 16; i++) {
GC_gcollect();
-# ifdef FINALIZE_ON_DEMAND
- late_finalize_count +=
-# endif
+# ifndef GC_NO_FINALIZATION
+# ifdef FINALIZE_ON_DEMAND
+ late_finalize_count +=
+# endif
GC_invoke_finalizers();
+# endif
}
if (GC_print_stats) {
struct GC_stack_base sb;
GC_printf("Allocated %d stubborn objects\n", stubborn_count);
GC_printf("Finalized %d/%d objects - ",
finalized_count, finalizable_count);
-# ifdef FINALIZE_ON_DEMAND
+# ifndef GC_NO_FINALIZATION
+# ifdef FINALIZE_ON_DEMAND
if (finalized_count != late_finalize_count) {
GC_printf("Demand finalization error\n");
FAIL;
}
-# endif
- if (finalized_count > finalizable_count
- || finalized_count < finalizable_count/2) {
+# endif
+ if (finalized_count > finalizable_count
+ || finalized_count < finalizable_count/2) {
GC_printf("finalization is probably broken\n");
FAIL;
- } else {
+ } else {
GC_printf("finalization is probably ok\n");
- }
- still_live = 0;
- for (i = 0; i < MAX_FINALIZED; i++) {
+ }
+ still_live = 0;
+ for (i = 0; i < MAX_FINALIZED; i++) {
if (live_indicators[i] != 0) {
still_live++;
}
- }
- i = finalizable_count - finalized_count - still_live;
- if (0 != i) {
+ }
+ i = finalizable_count - finalized_count - still_live;
+ if (0 != i) {
GC_printf("%d disappearing links remain and %d more objects "
"were not finalized\n", still_live, i);
if (i > 10) {
} else {
GC_printf("\tSlightly suspicious, but probably OK\n");
}
- }
+ }
+# endif
GC_printf("Total number of bytes allocated is %lu\n",
(unsigned long)GC_get_total_bytes());
GC_printf("Final heap size is %lu bytes\n",
lp -> ld_descriptor = leaf.ld_descriptor;
((volatile word *)op)[GRANULES_TO_WORDS(lg) - 1] = (word)lp;
} else {
+# ifndef GC_NO_FINALIZATION
size_t lw = GRANULES_TO_WORDS(lg);
((word *)op)[lw - 1] = (word)complex_descr;
/* Make sure the descriptor is cleared once there is any danger */
/* it may have been collected. */
if (GC_general_register_disappearing_link((void * *)((word *)op+lw-1),
- op) == GC_NO_MEMORY) {
+ op) == GC_NO_MEMORY)
+# endif
+ {
/* Couldn't register it due to lack of memory. Punt. */
/* This will probably fail too, but gives the recovery code */
/* a chance. */