From 9110a741e35c54e46c00662ddc420575376c5947 Mon Sep 17 00:00:00 2001 From: Bryce McKinlay Date: Mon, 21 May 2001 08:35:14 +0000 Subject: Imported version version 6.0alpha7. * README, README.Mac, README.OS2, README.QUICK, README.alpha, README.amiga, README.debugging, README.dj, README.hp, README.linux, README.rs6000, README.sgi, README.solaris2, README.uts, README.win32, SCoptions.amiga, backptr.h, barrett_diagram, dbg_mlc.h, gc.h, gc.man, gc_alloc.h, gc_cpp.h, gc_hdrs.h, gc_mark.h, gc_priv.h, gc_private.h, gc_typed.h, gcconfig.h, hpux_irix_threads.c, makefile.depend, nursery.c, solaris_threads.h, test.c, test_cpp.cc, weakpointer.h, cord/README, cord/SCOPTIONS.amiga, cord/SMakefile.amiga, cord/cord.h, cord/ec.h, cord/gc.h, cord/private/cord_pos.h, include/backptr.h, include/gc_copy_descr.h, include/gc_nursery.h: Remove obsolete/moved files. From-SVN: r42379 --- boehm-gc/reclaim.c | 410 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 237 insertions(+), 173 deletions(-) (limited to 'boehm-gc/reclaim.c') diff --git a/boehm-gc/reclaim.c b/boehm-gc/reclaim.c index 4ace110..f8f057d 100644 --- a/boehm-gc/reclaim.c +++ b/boehm-gc/reclaim.c @@ -15,11 +15,18 @@ */ #include -#include "gc_priv.h" +#include "private/gc_priv.h" signed_word GC_mem_found = 0; /* Number of words of memory reclaimed */ +#ifdef PARALLEL_MARK + word GC_fl_builder_count = 0; + /* Number of threads currently building free lists without */ + /* holding GC lock. It is not safe to collect if this is */ + /* nonzero. */ +#endif /* PARALLEL_MARK */ + static void report_leak(p, sz) ptr_t p; word sz; @@ -54,9 +61,12 @@ word sz; GC_bool GC_block_empty(hhdr) register hdr * hhdr; { + /* We treat hb_marks as an array of words here, even if it is */ + /* actually an array of bytes. Since we only check for zero, there */ + /* are no endian-ness issues. */ register word *p = (word *)(&(hhdr -> hb_marks[0])); register word * plim = - (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ])); + (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ])); while (p < plim) { if (*p++) return(FALSE); } @@ -70,7 +80,45 @@ register hdr * hhdr; # define GC_block_nearly_full1(hhdr, pat1) DONT_KNOW # define GC_block_nearly_full3(hhdr, pat1, pat2) DONT_KNOW # define GC_block_nearly_full(hhdr) DONT_KNOW -#else +#endif + +#if !defined(SMALL_CONFIG) && defined(USE_MARK_BYTES) + +# define GC_block_nearly_full1(hhdr, pat1) GC_block_nearly_full(hhdr) +# define GC_block_nearly_full3(hhdr, pat1, pat2) GC_block_nearly_full(hhdr) + + +GC_bool GC_block_nearly_full(hhdr) +register hdr * hhdr; +{ + /* We again treat hb_marks as an array of words, even though it */ + /* isn't. We first sum up all the words, resulting in a word */ + /* containing 4 or 8 separate partial sums. */ + /* We then sum the bytes in the word of partial sums. */ + /* This is still endian independant. This fails if the partial */ + /* sums can overflow. */ +# if (BYTES_TO_WORDS(MARK_BITS_SZ)) >= 256 + --> potential overflow; fix the code +# endif + register word *p = (word *)(&(hhdr -> hb_marks[0])); + register word * plim = + (word *)(&(hhdr -> hb_marks[MARK_BITS_SZ])); + word sum_vector = 0; + unsigned sum; + while (p < plim) { + sum_vector += *p; + ++p; + } + sum = 0; + while (sum_vector > 0) { + sum += sum_vector & 0xff; + sum_vector >>= 8; + } + return (sum > BYTES_TO_WORDS(7*HBLKSIZE/8)/(hhdr -> hb_sz)); +} +#endif /* USE_MARK_BYTES */ + +#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) /* * Test whether nearly all of the mark words consist of the same @@ -139,8 +187,6 @@ hdr *hhdr; # if CPP_WORDSZ != 32 && CPP_WORDSZ != 64 return DONT_KNOW; /* Shouldn't be used in any standard config. */ # endif - if (0 != HDR_WORDS) return DONT_KNOW; - /* Also shouldn't happen */ # if CPP_WORDSZ == 32 switch(sz) { case 1: @@ -194,12 +240,28 @@ hdr *hhdr; } # endif } -#endif /* !SMALL_CONFIG */ +#endif /* !SMALL_CONFIG && !USE_MARK_BYTES */ -# ifdef GATHERSTATS +/* We keep track of reclaimed memory if we are either asked to, or */ +/* we are using the parallel marker. In the latter case, we assume */ +/* that most allocation goes through GC_malloc_many for scalability. */ +/* GC_malloc_many needs the count anyway. */ +# if defined(GATHERSTATS) || defined(PARALLEL_MARK) # define INCR_WORDS(sz) n_words_found += (sz) +# define COUNT_PARAM , count +# define COUNT_ARG , count +# define COUNT_DECL signed_word * count; +# define NWORDS_DECL signed_word n_words_found = 0; +# define COUNT_UPDATE *count += n_words_found; +# define MEM_FOUND_ADDR , &GC_mem_found # else # define INCR_WORDS(sz) +# define COUNT_PARAM +# define COUNT_ARG +# define COUNT_DECL +# define NWORDS_DECL +# define COUNT_UPDATE +# define MEM_FOUND_ADDR # endif /* * Restore unmarked small objects in h of size sz to the object @@ -207,20 +269,20 @@ hdr *hhdr; * Clears unmarked objects. */ /*ARGSUSED*/ -ptr_t GC_reclaim_clear(hbp, hhdr, sz, list) +ptr_t GC_reclaim_clear(hbp, hhdr, sz, list COUNT_PARAM) register struct hblk *hbp; /* ptr to current heap block */ register hdr * hhdr; register ptr_t list; register word sz; +COUNT_DECL { register int word_no; register word *p, *q, *plim; -# ifdef GATHERSTATS - register int n_words_found = 0; -# endif + NWORDS_DECL + GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp)); p = (word *)(hbp->hb_body); - word_no = HDR_WORDS; + word_no = 0; plim = (word *)((((word)hbp) + HBLKSIZE) - WORDS_TO_BYTES(sz)); @@ -235,37 +297,45 @@ register word sz; list = ((ptr_t)p); /* Clear object, advance p to next object in the process */ q = p + sz; - p++; /* Skip link field */ - while (p < q) { +# ifdef USE_MARK_BYTES + GC_ASSERT(!(sz & 1) + && !((word)p & (2 * sizeof(word) - 1))); + p[1] = 0; + p += 2; + while (p < q) { + CLEAR_DOUBLE(p); + p += 2; + } +# else + p++; /* Skip link field */ + while (p < q) { *p++ = 0; - } + } +# endif } word_no += sz; } -# ifdef GATHERSTATS - GC_mem_found += n_words_found; -# endif + COUNT_UPDATE return(list); } -#ifndef SMALL_CONFIG +#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) /* * A special case for 2 word composite objects (e.g. cons cells): */ /*ARGSUSED*/ -ptr_t GC_reclaim_clear2(hbp, hhdr, list) +ptr_t GC_reclaim_clear2(hbp, hhdr, list COUNT_PARAM) register struct hblk *hbp; /* ptr to current heap block */ hdr * hhdr; register ptr_t list; +COUNT_DECL { - register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]); + register word * mark_word_addr = &(hhdr->hb_marks[0]); register word *p, *plim; -# ifdef GATHERSTATS - register int n_words_found = 0; -# endif register word mark_word; register int i; + NWORDS_DECL # define DO_OBJ(start_displ) \ if (!(mark_word & ((word)1 << start_displ))) { \ p[start_displ] = (word)list; \ @@ -289,9 +359,7 @@ register ptr_t list; mark_word >>= 8; } } -# ifdef GATHERSTATS - GC_mem_found += n_words_found; -# endif + COUNT_UPDATE return(list); # undef DO_OBJ } @@ -300,17 +368,16 @@ register ptr_t list; * Another special case for 4 word composite objects: */ /*ARGSUSED*/ -ptr_t GC_reclaim_clear4(hbp, hhdr, list) +ptr_t GC_reclaim_clear4(hbp, hhdr, list COUNT_PARAM) register struct hblk *hbp; /* ptr to current heap block */ hdr * hhdr; register ptr_t list; +COUNT_DECL { - register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]); + register word * mark_word_addr = &(hhdr->hb_marks[0]); register word *p, *plim; -# ifdef GATHERSTATS - register int n_words_found = 0; -# endif register word mark_word; + NWORDS_DECL # define DO_OBJ(start_displ) \ if (!(mark_word & ((word)1 << start_displ))) { \ p[start_displ] = (word)list; \ @@ -346,31 +413,27 @@ register ptr_t list; # endif p += WORDSZ; } -# ifdef GATHERSTATS - GC_mem_found += n_words_found; -# endif + COUNT_UPDATE return(list); # undef DO_OBJ } -#endif /* !SMALL_CONFIG */ +#endif /* !SMALL_CONFIG && !USE_MARK_BYTES */ /* The same thing, but don't clear objects: */ /*ARGSUSED*/ -ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list) +ptr_t GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_PARAM) register struct hblk *hbp; /* ptr to current heap block */ register hdr * hhdr; register ptr_t list; register word sz; +COUNT_DECL { - register int word_no; + register int word_no = 0; register word *p, *plim; -# ifdef GATHERSTATS - register int n_words_found = 0; -# endif + NWORDS_DECL p = (word *)(hbp->hb_body); - word_no = HDR_WORDS; plim = (word *)((((word)hbp) + HBLKSIZE) - WORDS_TO_BYTES(sz)); @@ -385,9 +448,7 @@ register word sz; p += sz; word_no += sz; } -# ifdef GATHERSTATS - GC_mem_found += n_words_found; -# endif + COUNT_UPDATE return(list); } @@ -398,14 +459,13 @@ register struct hblk *hbp; /* ptr to current heap block */ register hdr * hhdr; register word sz; { - register int word_no; + register int word_no = 0; register word *p, *plim; # ifdef GATHERSTATS register int n_words_found = 0; # endif p = (word *)(hbp->hb_body); - word_no = HDR_WORDS; plim = (word *)((((word)hbp) + HBLKSIZE) - WORDS_TO_BYTES(sz)); @@ -419,23 +479,22 @@ register word sz; } } -#ifndef SMALL_CONFIG +#if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) /* * Another special case for 2 word atomic objects: */ /*ARGSUSED*/ -ptr_t GC_reclaim_uninit2(hbp, hhdr, list) +ptr_t GC_reclaim_uninit2(hbp, hhdr, list COUNT_PARAM) register struct hblk *hbp; /* ptr to current heap block */ hdr * hhdr; register ptr_t list; +COUNT_DECL { - register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]); + register word * mark_word_addr = &(hhdr->hb_marks[0]); register word *p, *plim; -# ifdef GATHERSTATS - register int n_words_found = 0; -# endif register word mark_word; register int i; + NWORDS_DECL # define DO_OBJ(start_displ) \ if (!(mark_word & ((word)1 << start_displ))) { \ p[start_displ] = (word)list; \ @@ -458,9 +517,7 @@ register ptr_t list; mark_word >>= 8; } } -# ifdef GATHERSTATS - GC_mem_found += n_words_found; -# endif + COUNT_UPDATE return(list); # undef DO_OBJ } @@ -469,17 +526,16 @@ register ptr_t list; * Another special case for 4 word atomic objects: */ /*ARGSUSED*/ -ptr_t GC_reclaim_uninit4(hbp, hhdr, list) +ptr_t GC_reclaim_uninit4(hbp, hhdr, list COUNT_PARAM) register struct hblk *hbp; /* ptr to current heap block */ hdr * hhdr; register ptr_t list; +COUNT_DECL { - register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]); + register word * mark_word_addr = &(hhdr->hb_marks[0]); register word *p, *plim; -# ifdef GATHERSTATS - register int n_words_found = 0; -# endif register word mark_word; + NWORDS_DECL # define DO_OBJ(start_displ) \ if (!(mark_word & ((word)1 << start_displ))) { \ p[start_displ] = (word)list; \ @@ -513,27 +569,24 @@ register ptr_t list; # endif p += WORDSZ; } -# ifdef GATHERSTATS - GC_mem_found += n_words_found; -# endif + COUNT_UPDATE return(list); # undef DO_OBJ } /* Finally the one word case, which never requires any clearing: */ /*ARGSUSED*/ -ptr_t GC_reclaim1(hbp, hhdr, list) +ptr_t GC_reclaim1(hbp, hhdr, list COUNT_PARAM) register struct hblk *hbp; /* ptr to current heap block */ hdr * hhdr; register ptr_t list; +COUNT_DECL { - register word * mark_word_addr = &(hhdr->hb_marks[divWORDSZ(HDR_WORDS)]); + register word * mark_word_addr = &(hhdr->hb_marks[0]); register word *p, *plim; -# ifdef GATHERSTATS - register int n_words_found = 0; -# endif register word mark_word; register int i; + NWORDS_DECL # define DO_OBJ(start_displ) \ if (!(mark_word & ((word)1 << start_displ))) { \ p[start_displ] = (word)list; \ @@ -556,127 +609,102 @@ register ptr_t list; mark_word >>= 4; } } -# ifdef GATHERSTATS - GC_mem_found += n_words_found; -# endif + COUNT_UPDATE return(list); # undef DO_OBJ } -#endif /* !SMALL_CONFIG */ +#endif /* !SMALL_CONFIG && !USE_MARK_BYTES */ /* - * Restore unmarked small objects in the block pointed to by hbp - * to the appropriate object free list. - * If entirely empty blocks are to be completely deallocated, then - * caller should perform that check. + * Generic procedure to rebuild a free list in hbp. + * Also called directly from GC_malloc_many. */ -void GC_reclaim_small_nonempty_block(hbp, report_if_found) -register struct hblk *hbp; /* ptr to current heap block */ -int report_if_found; /* Abort if a reclaimable object is found */ +ptr_t GC_reclaim_generic(hbp, hhdr, sz, init, list COUNT_PARAM) +struct hblk *hbp; /* ptr to current heap block */ +hdr * hhdr; +GC_bool init; +ptr_t list; +word sz; +COUNT_DECL { - hdr * hhdr; - word sz; /* size of objects in current block */ - struct obj_kind * ok; - ptr_t * flh; - int kind; - GC_bool full; - - hhdr = HDR(hbp); - sz = hhdr -> hb_sz; - hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no; - kind = hhdr -> hb_obj_kind; - ok = &GC_obj_kinds[kind]; - flh = &(ok -> ok_freelist[sz]); + ptr_t result = list; - if (report_if_found) { - GC_reclaim_check(hbp, hhdr, sz); - } else if (ok -> ok_init) { + GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr); + if (init) { switch(sz) { -# ifndef SMALL_CONFIG +# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) case 1: -# if CPP_WORDSZ == 64 - full = GC_block_nearly_full1(hhdr, 0xffffffffffffffffl); -# else - full = GC_block_nearly_full1(hhdr, 0xffffffffl); -# endif - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - /* In the DONT_KNOW case, we let reclaim fault. */ - *flh = GC_reclaim1(hbp, hhdr, *flh); + /* We now issue the hint even if GC_nearly_full returned */ + /* DONT_KNOW. */ + GC_write_hint(hbp); + result = GC_reclaim1(hbp, hhdr, list COUNT_ARG); break; case 2: -# if CPP_WORDSZ == 64 - full = GC_block_nearly_full1(hhdr, 0x5555555555555555l); -# else - full = GC_block_nearly_full1(hhdr, 0x55555555l); -# endif - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - *flh = GC_reclaim_clear2(hbp, hhdr, *flh); + GC_write_hint(hbp); + result = GC_reclaim_clear2(hbp, hhdr, list COUNT_ARG); break; case 4: -# if CPP_WORDSZ == 64 - full = GC_block_nearly_full1(hhdr, 0x1111111111111111l); -# else - full = GC_block_nearly_full1(hhdr, 0x11111111l); -# endif - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - *flh = GC_reclaim_clear4(hbp, hhdr, *flh); + GC_write_hint(hbp); + result = GC_reclaim_clear4(hbp, hhdr, list COUNT_ARG); break; -# endif +# endif /* !SMALL_CONFIG && !USE_MARK_BYTES */ default: - full = GC_block_nearly_full(hhdr); - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - *flh = GC_reclaim_clear(hbp, hhdr, sz, *flh); + GC_write_hint(hbp); + result = GC_reclaim_clear(hbp, hhdr, sz, list COUNT_ARG); break; } } else { switch(sz) { -# ifndef SMALL_CONFIG +# if !defined(SMALL_CONFIG) && !defined(USE_MARK_BYTES) case 1: -# if CPP_WORDSZ == 64 - full = GC_block_nearly_full1(hhdr, 0xffffffffffffffffl); -# else - full = GC_block_nearly_full1(hhdr, 0xffffffffl); -# endif - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - *flh = GC_reclaim1(hbp, hhdr, *flh); + GC_write_hint(hbp); + result = GC_reclaim1(hbp, hhdr, list COUNT_ARG); break; case 2: -# if CPP_WORDSZ == 64 - full = GC_block_nearly_full1(hhdr, 0x5555555555555555l); -# else - full = GC_block_nearly_full1(hhdr, 0x55555555l); -# endif - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - *flh = GC_reclaim_uninit2(hbp, hhdr, *flh); + GC_write_hint(hbp); + result = GC_reclaim_uninit2(hbp, hhdr, list COUNT_ARG); break; case 4: -# if CPP_WORDSZ == 64 - full = GC_block_nearly_full1(hhdr, 0x1111111111111111l); -# else - full = GC_block_nearly_full1(hhdr, 0x11111111l); -# endif - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - *flh = GC_reclaim_uninit4(hbp, hhdr, *flh); + GC_write_hint(hbp); + result = GC_reclaim_uninit4(hbp, hhdr, list COUNT_ARG); break; -# endif +# endif /* !SMALL_CONFIG && !USE_MARK_BYTES */ default: - full = GC_block_nearly_full(hhdr); - if (TRUE == full) goto out; - if (FALSE == full) GC_write_hint(hbp); - *flh = GC_reclaim_uninit(hbp, hhdr, sz, *flh); + GC_write_hint(hbp); + result = GC_reclaim_uninit(hbp, hhdr, sz, list COUNT_ARG); break; } } -out: - if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(hhdr); + if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr); + return result; +} + +/* + * Restore unmarked small objects in the block pointed to by hbp + * to the appropriate object free list. + * If entirely empty blocks are to be completely deallocated, then + * caller should perform that check. + */ +void GC_reclaim_small_nonempty_block(hbp, report_if_found COUNT_PARAM) +register struct hblk *hbp; /* ptr to current heap block */ +int report_if_found; /* Abort if a reclaimable object is found */ +COUNT_DECL +{ + hdr *hhdr = HDR(hbp); + word sz = hhdr -> hb_sz; + int kind = hhdr -> hb_obj_kind; + struct obj_kind * ok = &GC_obj_kinds[kind]; + ptr_t * flh = &(ok -> ok_freelist[sz]); + + hhdr -> hb_last_reclaimed = (unsigned short) GC_gc_no; + + if (report_if_found) { + GC_reclaim_check(hbp, hhdr, sz); + } else { + *flh = GC_reclaim_generic(hbp, hhdr, sz, ok -> ok_init, + *flh MEM_FOUND_ADDR); + } } /* @@ -687,9 +715,13 @@ out: * If report_if_found is TRUE, then process any block immediately, and * simply report free objects; do not actually reclaim them. */ -void GC_reclaim_block(hbp, report_if_found) -register struct hblk *hbp; /* ptr to current heap block */ -word report_if_found; /* Abort if a reclaimable object is found */ +# if defined(__STDC__) || defined(__cplusplus) + void GC_reclaim_block(register struct hblk *hbp, word report_if_found) +# else + void GC_reclaim_block(hbp, report_if_found) + register struct hblk *hbp; /* ptr to current heap block */ + word report_if_found; /* Abort if a reclaimable object is found */ +# endif { register hdr * hhdr; register word sz; /* size of objects in current block */ @@ -701,10 +733,14 @@ word report_if_found; /* Abort if a reclaimable object is found */ ok = &GC_obj_kinds[hhdr -> hb_obj_kind]; if( sz > MAXOBJSZ ) { /* 1 big object */ - if( !mark_bit_from_hdr(hhdr, HDR_WORDS) ) { + if( !mark_bit_from_hdr(hhdr, 0) ) { if (report_if_found) { - FOUND_FREE(hbp, HDR_WORDS); + FOUND_FREE(hbp, 0); } else { + word blocks = OBJ_SZ_TO_BLOCKS(sz); + if (blocks > 1) { + GC_large_allocd_bytes -= blocks * HBLKSIZE; + } # ifdef GATHERSTATS GC_mem_found += sz; # endif @@ -714,18 +750,23 @@ word report_if_found; /* Abort if a reclaimable object is found */ } else { GC_bool empty = GC_block_empty(hhdr); if (report_if_found) { - GC_reclaim_small_nonempty_block(hbp, (int)report_if_found); + GC_reclaim_small_nonempty_block(hbp, (int)report_if_found + MEM_FOUND_ADDR); } else if (empty) { # ifdef GATHERSTATS GC_mem_found += BYTES_TO_WORDS(HBLKSIZE); # endif GC_freehblk(hbp); - } else { + } else if (TRUE != GC_block_nearly_full(hhdr)){ /* group of smaller objects, enqueue the real work */ rlh = &(ok -> ok_reclaim_list[sz]); hhdr -> hb_next = *rlh; *rlh = hbp; - } + } /* else not worth salvaging. */ + /* We used to do the nearly_full check later, but we */ + /* already have the right cache context here. Also */ + /* doing it here avoids some silly lock contention in */ + /* GC_malloc_many. */ } } @@ -736,6 +777,23 @@ word report_if_found; /* Abort if a reclaimable object is found */ static size_t number_of_blocks; static size_t total_bytes; +#ifdef USE_MARK_BYTES + +/* Return the number of set mark bits in the given header */ +int GC_n_set_marks(hhdr) +hdr * hhdr; +{ + register int result = 0; + register int i; + + for (i = 0; i < MARK_BITS_SZ; i++) { + result += hhdr -> hb_marks[i]; + } + return(result); +} + +#else + /* Number of set bits in a word. Not performance critical. */ static int set_bits(n) word n; @@ -763,10 +821,16 @@ hdr * hhdr; return(result); } +#endif /* !USE_MARK_BYTES */ + /*ARGSUSED*/ -void GC_print_block_descr(h, dummy) -struct hblk *h; -word dummy; +# if defined(__STDC__) || defined(__cplusplus) + void GC_print_block_descr(struct hblk *h, word dummy) +# else + void GC_print_block_descr(h, dummy) + struct hblk *h; + word dummy; +# endif { register hdr * hhdr = HDR(h); register size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz); @@ -774,7 +838,7 @@ word dummy; GC_printf3("(%lu:%lu,%lu)", (unsigned long)(hhdr -> hb_obj_kind), (unsigned long)bytes, (unsigned long)(GC_n_set_marks(hhdr))); - bytes += HDR_BYTES + HBLKSIZE-1; + bytes += HBLKSIZE-1; bytes &= ~(HBLKSIZE-1); total_bytes += bytes; number_of_blocks++; @@ -861,7 +925,7 @@ int kind; while ((hbp = *rlh) != 0) { hhdr = HDR(hbp); *rlh = hhdr -> hb_next; - GC_reclaim_small_nonempty_block(hbp, FALSE); + GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR); if (*flh != 0) break; } } @@ -909,7 +973,7 @@ GC_bool ignore_old; /* It's likely we'll need it this time, too */ /* It's been touched recently, so this */ /* shouldn't trigger paging. */ - GC_reclaim_small_nonempty_block(hbp, FALSE); + GC_reclaim_small_nonempty_block(hbp, FALSE MEM_FOUND_ADDR); } } } -- cgit v1.1