From c14335e44d3d325118cd9ecc7983e688581a1a49 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Mon, 6 Feb 2012 19:49:06 +0400 Subject: [PATCH] Allow to exclude finalization support by GC_NO_FINALIZATION macro * 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. --- alloc.c | 8 ++++-- dbg_mlc.c | 4 +++ doc/README.macros | 2 ++ finalize.c | 25 +++---------------- include/private/gc_priv.h | 42 +++++++++++++++++-------------- mark_rts.c | 4 ++- misc.c | 20 +++++++++++++++ tests/test.c | 52 ++++++++++++++++++++++++--------------- typd_mlc.c | 5 +++- 9 files changed, 98 insertions(+), 64 deletions(-) diff --git a/alloc.c b/alloc.c index a8231281..2a6b9fa8 100644 --- a/alloc.c +++ b/alloc.c @@ -841,7 +841,9 @@ STATIC void GC_finish_collection(void) /* 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 @@ -923,7 +925,9 @@ STATIC void GC_finish_collection(void) 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), diff --git a/dbg_mlc.c b/dbg_mlc.c index 932aaaca..94cbe162 100644 --- a/dbg_mlc.c +++ b/dbg_mlc.c @@ -987,6 +987,8 @@ GC_INNER GC_bool GC_check_leaked(ptr_t base) #endif /* !SHORT_DBG_HDRS */ +#ifndef GC_NO_FINALIZATION + struct closure { GC_finalization_proc cl_fn; void * cl_data; @@ -1165,6 +1167,8 @@ GC_API void GC_CALL GC_debug_register_finalizer_ignore_self 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); diff --git a/doc/README.macros b/doc/README.macros index 09a05fca..e04037dc 100644 --- a/doc/README.macros +++ b/doc/README.macros @@ -248,6 +248,8 @@ FINALIZE_ON_DEMAND Causes finalizers to be run only in response 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. diff --git a/finalize.c b/finalize.c index a4c7ef5a..012c3357 100644 --- a/finalize.c +++ b/finalize.c @@ -16,6 +16,8 @@ #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. */ @@ -949,27 +951,6 @@ GC_INNER void GC_notify_or_invoke_finalizers(void) (*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) { @@ -985,3 +966,5 @@ GC_API void * GC_CALL GC_call_with_alloc_lock(GC_fn_type fn, ready, (long)GC_old_dl_entries - (long)GC_dl_entries); } #endif /* !SMALL_CONFIG */ + +#endif /* !GC_NO_FINALIZATION */ diff --git a/include/private/gc_priv.h b/include/private/gc_priv.h index e2af73f3..4466e00a 100644 --- a/include/private/gc_priv.h +++ b/include/private/gc_priv.h @@ -247,7 +247,29 @@ typedef char * ptr_t; /* A generic pointer to which we can add */ /* 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 @@ -1517,7 +1539,6 @@ GC_EXTERN void (*GC_push_other_roots)(void); /* 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 @@ -1803,20 +1824,6 @@ GC_INNER void GC_remove_counts(struct hblk * h, size_t sz); /* 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. */ @@ -1961,9 +1968,6 @@ void GC_print_block_list(void); 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 */ diff --git a/mark_rts.c b/mark_rts.c index 8bd9ddc2..a57ac3e9 100644 --- a/mark_rts.c +++ b/mark_rts.c @@ -706,7 +706,9 @@ GC_INNER void (*GC_push_typed_structures)(void) = 0; */ 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 diff --git a/misc.c b/misc.c index 3d6a579b..68d2fe46 100644 --- a/misc.c +++ b/misc.c @@ -1562,6 +1562,26 @@ GC_API unsigned GC_CALL GC_new_proc(GC_mark_proc proc) 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; diff --git a/tests/test.c b/tests/test.c index cf6c383d..5201d4b4 100644 --- a/tests/test.c +++ b/tests/test.c @@ -732,8 +732,10 @@ tn * mktree(int n) 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 @@ -747,7 +749,9 @@ tn * mktree(int n) # 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 @@ -758,6 +762,7 @@ tn * mktree(int n) # 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) { @@ -795,6 +800,7 @@ tn * mktree(int n) GC_printf("GC_general_register_disappearing_link failed 2\n"); FAIL; } +# endif GC_reachable_here(result); } return(result); @@ -1281,9 +1287,11 @@ void check_heap_stats(void) { 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 @@ -1322,10 +1330,12 @@ void check_heap_stats(void) 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; @@ -1348,27 +1358,28 @@ void check_heap_stats(void) 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) { @@ -1376,7 +1387,8 @@ void check_heap_stats(void) } 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", diff --git a/typd_mlc.c b/typd_mlc.c index ce5c4c82..0326532a 100644 --- a/typd_mlc.c +++ b/typd_mlc.c @@ -714,13 +714,16 @@ GC_API void * GC_CALL GC_calloc_explicitly_typed(size_t n, size_t lb, 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. */ -- 2.40.0