=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/gc/dbg_mlc.c,v retrieving revision 1.4 retrieving revision 1.7 diff -u -p -r1.4 -r1.7 --- OpenXM_contrib2/asir2000/gc/dbg_mlc.c 2001/04/20 07:39:18 1.4 +++ OpenXM_contrib2/asir2000/gc/dbg_mlc.c 2003/06/24 05:11:32 1.7 @@ -26,7 +26,7 @@ GC_API void GC_register_finalizer_no_order /* Check whether object with base pointer p has debugging info */ /* p is assumed to point to a legitimate object in our part */ /* of the heap. */ -/* This excludes the check as to whether tha back pointer is */ +/* This excludes the check as to whether the back pointer is */ /* odd, which is added by the GC_HAS_DEBUG_INFO macro. */ /* Note that if DBG_HDRS_ALL is set, uncollectable objects */ /* on free lists may not have debug information set. Thus it's */ @@ -40,7 +40,7 @@ ptr_t p; register word sz = GC_size((ptr_t) ohdr); if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body) - || sz < sizeof (oh)) { + || sz < DEBUG_BYTES + EXTRA_BYTES) { return(FALSE); } if (ohdr -> oh_sz == sz) { @@ -60,7 +60,7 @@ ptr_t p; # include # if defined(LINUX) || defined(SUNOS4) || defined(SUNOS5) \ - || defined(HPUX) || defined(IRIX) || defined(OSF1) + || defined(HPUX) || defined(IRIX5) || defined(OSF1) # define RANDOM() random() # else # define RANDOM() (long)rand() @@ -228,12 +228,14 @@ ptr_t p; #endif /* KEEP_BACK_PTRS */ +# define CROSSES_HBLK(p, sz) \ + (((word)(p + sizeof(oh) + sz - 1) ^ (word)p) >= HBLKSIZE) /* Store debugging info into p. Return displaced pointer. */ /* Assumes we don't hold allocation lock. */ ptr_t GC_store_debug_info(p, sz, string, integer) register ptr_t p; /* base pointer */ word sz; /* bytes */ -char * string; +GC_CONST char * string; word integer; { register word * result = (word *)((oh *)p + 1); @@ -243,16 +245,21 @@ word integer; /* But that's expensive. And this way things should only appear */ /* inconsistent while we're in the handler. */ LOCK(); + GC_ASSERT(GC_size(p) >= sizeof(oh) + sz); + GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz))); # ifdef KEEP_BACK_PTRS ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); # endif +# ifdef MAKE_BACK_GRAPH + ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0); +# endif ((oh *)p) -> oh_string = string; ((oh *)p) -> oh_int = integer; # ifndef SHORT_DBG_HDRS ((oh *)p) -> oh_sz = sz; ((oh *)p) -> oh_sf = START_FLAG ^ (word)result; ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] = - result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result; + result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result; # endif UNLOCK(); return((ptr_t)result); @@ -272,16 +279,21 @@ word integer; /* There is some argument that we should disable signals here. */ /* But that's expensive. And this way things should only appear */ /* inconsistent while we're in the handler. */ + GC_ASSERT(GC_size(p) >= sizeof(oh) + sz); + GC_ASSERT(!(SMALL_OBJ(sz) && CROSSES_HBLK(p, sz))); # ifdef KEEP_BACK_PTRS - ((oh *)p) -> oh_back_ptr = 0; + ((oh *)p) -> oh_back_ptr = HIDE_BACK_PTR(NOT_MARKED); # endif +# ifdef MAKE_BACK_GRAPH + ((oh *)p) -> oh_bg_ptr = HIDE_BACK_PTR((ptr_t)0); +# endif ((oh *)p) -> oh_string = string; ((oh *)p) -> oh_int = integer; # ifndef SHORT_DBG_HDRS ((oh *)p) -> oh_sz = sz; ((oh *)p) -> oh_sf = START_FLAG ^ (word)result; ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] = - result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result; + result[SIMPLE_ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result; # endif return((ptr_t)result); } @@ -305,9 +317,9 @@ register oh * ohdr; if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) { return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1)); } - if (((word *)body)[ROUNDED_UP_WORDS(ohdr -> oh_sz)] + if (((word *)body)[SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz)] != (END_FLAG ^ (word)body)) { - return((ptr_t)((word *)body + ROUNDED_UP_WORDS(ohdr -> oh_sz))); + return((ptr_t)((word *)body + SIMPLE_ROUNDED_UP_WORDS(ohdr -> oh_sz))); } return(0); } @@ -318,10 +330,11 @@ ptr_t p; { register oh * ohdr = (oh *)GC_base(p); + GC_ASSERT(!I_HOLD_LOCK()); GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh))); GC_err_puts(ohdr -> oh_string); # ifdef SHORT_DBG_HDRS - GC_err_printf1(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int)); + GC_err_printf1(":%ld)\n", (unsigned long)(ohdr -> oh_int)); # else GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int), (unsigned long)(ohdr -> oh_sz)); @@ -336,6 +349,7 @@ ptr_t p; ptr_t p; # endif { + GC_ASSERT(!I_HOLD_LOCK()); if (GC_HAS_DEBUG_INFO(p)) { GC_print_obj(p); } else { @@ -349,6 +363,7 @@ ptr_t p, clobbered_addr; { register oh * ohdr = (oh *)GC_base(p); + GC_ASSERT(!I_HOLD_LOCK()); GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr, (unsigned long)p); if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz)) @@ -370,14 +385,18 @@ ptr_t p, clobbered_addr; void GC_check_heap_proc GC_PROTO((void)); +void GC_print_all_smashed_proc GC_PROTO((void)); + void GC_do_nothing() {} void GC_start_debugging() { # ifndef SHORT_DBG_HDRS GC_check_heap = GC_check_heap_proc; + GC_print_all_smashed = GC_print_all_smashed_proc; # else GC_check_heap = GC_do_nothing; + GC_print_all_smashed = GC_do_nothing; # endif GC_print_heap_obj = GC_debug_print_heap_obj_proc; GC_debugging_started = TRUE; @@ -423,6 +442,62 @@ void GC_start_debugging() return (GC_store_debug_info(result, (word)lb, s, (word)i)); } +# ifdef __STDC__ + GC_PTR GC_debug_malloc_ignore_off_page(size_t lb, GC_EXTRA_PARAMS) +# else + GC_PTR GC_debug_malloc_ignore_off_page(lb, s, i) + size_t lb; + char * s; + int i; +# ifdef GC_ADD_CALLER + --> GC_ADD_CALLER not implemented for K&R C +# endif +# endif +{ + GC_PTR result = GC_malloc_ignore_off_page(lb + DEBUG_BYTES); + + if (result == 0) { + GC_err_printf1("GC_debug_malloc_ignore_off_page(%ld) returning NIL (", + (unsigned long) lb); + GC_err_puts(s); + GC_err_printf1(":%ld)\n", (unsigned long)i); + return(0); + } + if (!GC_debugging_started) { + GC_start_debugging(); + } + ADD_CALL_CHAIN(result, ra); + return (GC_store_debug_info(result, (word)lb, s, (word)i)); +} + +# ifdef __STDC__ + GC_PTR GC_debug_malloc_atomic_ignore_off_page(size_t lb, GC_EXTRA_PARAMS) +# else + GC_PTR GC_debug_malloc_atomic_ignore_off_page(lb, s, i) + size_t lb; + char * s; + int i; +# ifdef GC_ADD_CALLER + --> GC_ADD_CALLER not implemented for K&R C +# endif +# endif +{ + GC_PTR result = GC_malloc_atomic_ignore_off_page(lb + DEBUG_BYTES); + + if (result == 0) { + GC_err_printf1("GC_debug_malloc_atomic_ignore_off_page(%ld)" + " returning NIL (", (unsigned long) lb); + GC_err_puts(s); + GC_err_printf1(":%ld)\n", (unsigned long)i); + return(0); + } + if (!GC_debugging_started) { + GC_start_debugging(); + } + ADD_CALL_CHAIN(result, ra); + return (GC_store_debug_info(result, (word)lb, s, (word)i)); +} + # ifdef DBG_HDRS_ALL /* * An allocation function for internal use. @@ -441,7 +516,7 @@ void GC_start_debugging() (unsigned long) lb); return(0); } - ADD_CALL_CHAIN(result, ra); + ADD_CALL_CHAIN(result, GC_RETURN_ADDR); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); } @@ -455,7 +530,7 @@ void GC_start_debugging() (unsigned long) lb); return(0); } - ADD_CALL_CHAIN(result, ra); + ADD_CALL_CHAIN(result, GC_RETURN_ADDR); return (GC_store_debug_info_inner(result, (word)lb, "INTERNAL", (word)0)); } # endif @@ -586,7 +661,7 @@ GC_PTR p; int i; # endif { - GC_PTR result = GC_malloc_uncollectable(lb + DEBUG_BYTES); + GC_PTR result = GC_malloc_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); if (result == 0) { GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (", @@ -612,7 +687,8 @@ GC_PTR p; int i; # endif { - GC_PTR result = GC_malloc_atomic_uncollectable(lb + DEBUG_BYTES); + GC_PTR result = + GC_malloc_atomic_uncollectable(lb + UNCOLLECTABLE_DEBUG_BYTES); if (result == 0) { GC_err_printf1( @@ -768,6 +844,45 @@ void GC_debug_free_inner(GC_PTR p) } #ifndef SHORT_DBG_HDRS + +/* List of smashed objects. We defer printing these, since we can't */ +/* always print them nicely with the allocation lock held. */ +/* We put them here instead of in GC_arrays, since it may be useful to */ +/* be able to look at them with the debugger. */ +#define MAX_SMASHED 20 +ptr_t GC_smashed[MAX_SMASHED]; +unsigned GC_n_smashed = 0; + +# if defined(__STDC__) || defined(__cplusplus) + void GC_add_smashed(ptr_t smashed) +# else + void GC_add_smashed(smashed) + ptr_t smashed; +#endif +{ + GC_ASSERT(GC_is_marked(GC_base(smashed))); + GC_smashed[GC_n_smashed] = smashed; + if (GC_n_smashed < MAX_SMASHED - 1) ++GC_n_smashed; + /* In case of overflow, we keep the first MAX_SMASHED-1 */ + /* entries plus the last one. */ + GC_have_errors = TRUE; +} + +/* Print all objects on the list. Clear the list. */ +void GC_print_all_smashed_proc () +{ + unsigned i; + + GC_ASSERT(!I_HOLD_LOCK()); + if (GC_n_smashed == 0) return; + GC_err_printf0("GC_check_heap_block: found smashed heap objects:\n"); + for (i = 0; i < GC_n_smashed; ++i) { + GC_print_smashed_obj(GC_base(GC_smashed[i]), GC_smashed[i]); + GC_smashed[i] = 0; + } + GC_n_smashed = 0; +} + /* Check all marked objects in the given block for validity */ /*ARGSUSED*/ # if defined(__STDC__) || defined(__cplusplus) @@ -796,11 +911,7 @@ void GC_debug_free_inner(GC_PTR p) && GC_HAS_DEBUG_INFO((ptr_t)p)) { ptr_t clobbered = GC_check_annotated_obj((oh *)p); - if (clobbered != 0) { - GC_err_printf0( - "GC_check_heap_block: found smashed location at "); - GC_print_smashed_obj((ptr_t)p, clobbered); - } + if (clobbered != 0) GC_add_smashed(clobbered); } word_no += sz; p += sz; @@ -813,9 +924,11 @@ void GC_debug_free_inner(GC_PTR p) void GC_check_heap_proc() { # ifndef SMALL_CONFIG - if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) { - ABORT("Alignment problem: object header has inappropriate size\n"); - } +# ifdef ALIGN_DOUBLE + GC_STATIC_ASSERT((sizeof(oh) & (2 * sizeof(word) - 1)) == 0); +# else + GC_STATIC_ASSERT((sizeof(oh) & (sizeof(word) - 1)) == 0); +# endif # endif GC_apply_to_all_blocks(GC_check_heap_block, (word)0); } @@ -836,12 +949,12 @@ struct closure { # endif { struct closure * result = -# ifdef DBG_HDRS_ALL - (struct closure *) GC_debug_malloc(sizeof (struct closure), - GC_EXTRAS); -# else - (struct closure *) GC_malloc(sizeof (struct closure)); -# endif +# ifdef DBG_HDRS_ALL + (struct closure *) GC_debug_malloc(sizeof (struct closure), + GC_EXTRAS); +# else + (struct closure *) GC_malloc(sizeof (struct closure)); +# endif result -> cl_fn = fn; result -> cl_data = data; @@ -861,6 +974,28 @@ struct closure { (*(cl -> cl_fn))((GC_PTR)((char *)obj + sizeof(oh)), cl -> cl_data); } +/* Set ofn and ocd to reflect the values we got back. */ +static void store_old (obj, my_old_fn, my_old_cd, ofn, ocd) +GC_PTR obj; +GC_finalization_proc my_old_fn; +struct closure * my_old_cd; +GC_finalization_proc *ofn; +GC_PTR *ocd; +{ + if (0 != my_old_fn) { + if (my_old_fn != GC_debug_invoke_finalizer) { + GC_err_printf1("Debuggable object at 0x%lx had non-debug finalizer.\n", + obj); + /* This should probably be fatal. */ + } else { + if (ofn) *ofn = my_old_cd -> cl_fn; + if (ocd) *ocd = my_old_cd -> cl_data; + } + } else { + if (ofn) *ofn = 0; + if (ocd) *ocd = 0; + } +} # ifdef __STDC__ void GC_debug_register_finalizer(GC_PTR obj, GC_finalization_proc fn, @@ -875,14 +1010,21 @@ struct closure { GC_PTR *ocd; # endif { + GC_finalization_proc my_old_fn; + GC_PTR my_old_cd; ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( - "GC_register_finalizer called with non-base-pointer 0x%lx\n", + "GC_debug_register_finalizer called with non-base-pointer 0x%lx\n", obj); } - GC_register_finalizer(base, GC_debug_invoke_finalizer, - GC_make_closure(fn,cd), ofn, ocd); + if (0 == fn) { + GC_register_finalizer(base, 0, 0, &my_old_fn, &my_old_cd); + } else { + GC_register_finalizer(base, GC_debug_invoke_finalizer, + GC_make_closure(fn,cd), &my_old_fn, &my_old_cd); + } + store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); } # ifdef __STDC__ @@ -900,14 +1042,22 @@ struct closure { GC_PTR *ocd; # endif { + GC_finalization_proc my_old_fn; + GC_PTR my_old_cd; ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( - "GC_register_finalizer_no_order called with non-base-pointer 0x%lx\n", + "GC_debug_register_finalizer_no_order called with non-base-pointer 0x%lx\n", obj); } - GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer, - GC_make_closure(fn,cd), ofn, ocd); + if (0 == fn) { + GC_register_finalizer_no_order(base, 0, 0, &my_old_fn, &my_old_cd); + } else { + GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer, + GC_make_closure(fn,cd), &my_old_fn, + &my_old_cd); + } + store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); } # ifdef __STDC__ @@ -925,25 +1075,39 @@ struct closure { GC_PTR *ocd; # endif { + GC_finalization_proc my_old_fn; + GC_PTR my_old_cd; ptr_t base = GC_base(obj); if (0 == base || (ptr_t)obj - base != sizeof(oh)) { GC_err_printf1( - "GC_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n", + "GC_debug_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n", obj); } - GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer, - GC_make_closure(fn,cd), ofn, ocd); + if (0 == fn) { + GC_register_finalizer_ignore_self(base, 0, 0, &my_old_fn, &my_old_cd); + } else { + GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer, + GC_make_closure(fn,cd), &my_old_fn, + &my_old_cd); + } + store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); } +#ifdef GC_ADD_CALLER +# define RA GC_RETURN_ADDR, +#else +# define RA +#endif + GC_PTR GC_debug_malloc_replacement(lb) size_t lb; { - return GC_debug_malloc(lb, "unknown", 0); + return GC_debug_malloc(lb, RA "unknown", 0); } GC_PTR GC_debug_realloc_replacement(p, lb) GC_PTR p; size_t lb; { - return GC_debug_realloc(p, lb, "unknown", 0); + return GC_debug_realloc(p, lb, RA "unknown", 0); }