diff options
Diffstat (limited to 'boehm-gc/allchblk.c')
-rw-r--r-- | boehm-gc/allchblk.c | 408 |
1 files changed, 0 insertions, 408 deletions
diff --git a/boehm-gc/allchblk.c b/boehm-gc/allchblk.c deleted file mode 100644 index 7a5a3a1c3ab..00000000000 --- a/boehm-gc/allchblk.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers - * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. - * Copyright (c) 1998 by Silicon Graphics. All rights reserved. - * - * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED - * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. - * - * Permission is hereby granted to use or copy this program - * for any purpose, provided the above notices are retained on all copies. - * Permission to modify the code and to distribute modified code is granted, - * provided the above notices are retained, and a notice that the code was - * modified is included with the above copyright notice. - */ -/* Boehm, August 9, 1995 5:08 pm PDT */ - -#define DEBUG -#undef DEBUG -#include <stdio.h> -#include "gc_priv.h" - - -/* - * allocate/free routines for heap blocks - * Note that everything called from outside the garbage collector - * should be prepared to abort at any point as the result of a signal. - */ - -/* - * Free heap blocks are kept on a list sorted by address. - * The hb_hdr.hbh_sz field of a free heap block contains the length - * (in bytes) of the entire block. - * Neighbors are coalesced. - */ - -# define MAX_BLACK_LIST_ALLOC (2*HBLKSIZE) - /* largest block we will allocate starting on a black */ - /* listed block. Must be >= HBLKSIZE. */ - -struct hblk * GC_hblkfreelist = 0; - -struct hblk *GC_savhbp = (struct hblk *)0; /* heap block preceding next */ - /* block to be examined by */ - /* GC_allochblk. */ - -# if !defined(NO_DEBUGGING) -void GC_print_hblkfreelist() -{ - struct hblk * h = GC_hblkfreelist; - word total_free = 0; - hdr * hhdr = HDR(h); - word sz; - - while (h != 0) { - sz = hhdr -> hb_sz; - GC_printf2("0x%lx size %lu ", (unsigned long)h, (unsigned long)sz); - total_free += sz; - if (GC_is_black_listed(h, HBLKSIZE) != 0) { - GC_printf0("start black listed\n"); - } else if (GC_is_black_listed(h, hhdr -> hb_sz) != 0) { - GC_printf0("partially black listed\n"); - } else { - GC_printf0("not black listed\n"); - } - h = hhdr -> hb_next; - hhdr = HDR(h); - } - GC_printf1("Total of %lu bytes on free list\n", (unsigned long)total_free); -} - -# endif /* NO_DEBUGGING */ - -/* Initialize hdr for a block containing the indicated size and */ -/* kind of objects. */ -/* Return FALSE on failure. */ -static GC_bool setup_header(hhdr, sz, kind, flags) -register hdr * hhdr; -word sz; /* object size in words */ -int kind; -unsigned char flags; -{ - register word descr; - - /* Add description of valid object pointers */ - if (!GC_add_map_entry(sz)) return(FALSE); - hhdr -> hb_map = GC_obj_map[sz > MAXOBJSZ? 0 : sz]; - - /* Set size, kind and mark proc fields */ - hhdr -> hb_sz = sz; - hhdr -> hb_obj_kind = kind; - hhdr -> hb_flags = flags; - descr = GC_obj_kinds[kind].ok_descriptor; - if (GC_obj_kinds[kind].ok_relocate_descr) descr += WORDS_TO_BYTES(sz); - hhdr -> hb_descr = descr; - - /* Clear mark bits */ - GC_clear_hdr_marks(hhdr); - - hhdr -> hb_last_reclaimed = (unsigned short)GC_gc_no; - return(TRUE); -} - -#ifdef EXACT_FIRST -# define LAST_TRIP 2 -#else -# define LAST_TRIP 1 -#endif - -/* - * Allocate (and return pointer to) a heap block - * for objects of size sz words. - * - * NOTE: We set obj_map field in header correctly. - * Caller is resposnsible for building an object freelist in block. - * - * We clear the block if it is destined for large objects, and if - * kind requires that newly allocated objects be cleared. - */ -struct hblk * -GC_allochblk(sz, kind, flags) -word sz; -int kind; -unsigned char flags; /* IGNORE_OFF_PAGE or 0 */ -{ - register struct hblk *thishbp; - register hdr * thishdr; /* Header corr. to thishbp */ - register struct hblk *hbp; - register hdr * hhdr; /* Header corr. to hbp */ - struct hblk *prevhbp; - register hdr * phdr; /* Header corr. to prevhbp */ - signed_word size_needed; /* number of bytes in requested objects */ - signed_word size_avail; /* bytes available in this block */ - int trip_count = 0; - - size_needed = HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz); - - /* search for a big enough block in free list */ - hbp = GC_savhbp; - hhdr = HDR(hbp); - for(;;) { - - prevhbp = hbp; - phdr = hhdr; - hbp = (prevhbp == 0? GC_hblkfreelist : phdr->hb_next); - hhdr = HDR(hbp); - - if( prevhbp == GC_savhbp) { - if (trip_count == LAST_TRIP) return(0); - ++trip_count; - } - - if( hbp == 0 ) continue; - - size_avail = hhdr->hb_sz; -# ifdef EXACT_FIRST - if (trip_count <= 1 && size_avail != size_needed) continue; -# endif - if (size_avail < size_needed) continue; -# ifdef PRESERVE_LAST - if (size_avail != size_needed - && !GC_incremental - && GC_in_last_heap_sect(hbp) && GC_should_collect()) { - continue; - } -# endif - /* If the next heap block is obviously better, go on. */ - /* This prevents us from disassembling a single large block */ - /* to get tiny blocks. */ - { - signed_word next_size; - - thishbp = hhdr -> hb_next; - if (thishbp == 0) thishbp = GC_hblkfreelist; - thishdr = HDR(thishbp); - next_size = (signed_word)(thishdr -> hb_sz); - if (next_size < size_avail - && next_size >= size_needed - && !GC_is_black_listed(thishbp, (word)size_needed)) { - continue; - } - } - if ( !IS_UNCOLLECTABLE(kind) && - (kind != PTRFREE || size_needed > MAX_BLACK_LIST_ALLOC)) { - struct hblk * lasthbp = hbp; - ptr_t search_end = (ptr_t)hbp + size_avail - size_needed; - signed_word orig_avail = size_avail; - signed_word eff_size_needed = ((flags & IGNORE_OFF_PAGE)? - HBLKSIZE - : size_needed); - - - while ((ptr_t)lasthbp <= search_end - && (thishbp = GC_is_black_listed(lasthbp, - (word)eff_size_needed))) { - lasthbp = thishbp; - } - size_avail -= (ptr_t)lasthbp - (ptr_t)hbp; - thishbp = lasthbp; - if (size_avail >= size_needed) { - if (thishbp != hbp && GC_install_header(thishbp)) { - /* Split the block at thishbp */ - thishdr = HDR(thishbp); - /* GC_invalidate_map not needed, since we will */ - /* allocate this block. */ - thishdr -> hb_next = hhdr -> hb_next; - thishdr -> hb_sz = size_avail; - hhdr -> hb_sz = (ptr_t)thishbp - (ptr_t)hbp; - hhdr -> hb_next = thishbp; - /* Advance to thishbp */ - prevhbp = hbp; - phdr = hhdr; - hbp = thishbp; - hhdr = thishdr; - } - } else if (size_needed > (signed_word)BL_LIMIT - && orig_avail - size_needed - > (signed_word)BL_LIMIT) { - /* Punt, since anything else risks unreasonable heap growth. */ - WARN("Needed to allocate blacklisted block at 0x%lx\n", - (word)hbp); - thishbp = hbp; - size_avail = orig_avail; - } else if (size_avail == 0 - && size_needed == HBLKSIZE - && prevhbp != 0) { -# ifndef FIND_LEAK - static unsigned count = 0; - - /* The block is completely blacklisted. We need */ - /* to drop some such blocks, since otherwise we spend */ - /* all our time traversing them if pointerfree */ - /* blocks are unpopular. */ - /* A dropped block will be reconsidered at next GC. */ - if ((++count & 3) == 0) { - /* Allocate and drop the block in small chunks, to */ - /* maximize the chance that we will recover some */ - /* later. */ - struct hblk * limit = hbp + (hhdr->hb_sz/HBLKSIZE); - struct hblk * h; - - GC_words_wasted += hhdr->hb_sz; - phdr -> hb_next = hhdr -> hb_next; - for (h = hbp; h < limit; h++) { - if (h == hbp || GC_install_header(h)) { - hhdr = HDR(h); - (void) setup_header( - hhdr, - BYTES_TO_WORDS(HBLKSIZE - HDR_BYTES), - PTRFREE, 0); /* Cant fail */ - if (GC_debugging_started) { - BZERO(hbp + HDR_BYTES, HBLKSIZE - HDR_BYTES); - } - } - } - /* Restore hbp to point at free block */ - if (GC_savhbp == hbp) GC_savhbp = prevhbp; - hbp = prevhbp; - hhdr = phdr; - if (hbp == GC_savhbp) --trip_count; - } -# endif - } - } - if( size_avail >= size_needed ) { - /* found a big enough block */ - /* let thishbp --> the block */ - /* set prevhbp, hbp to bracket it */ - thishbp = hbp; - thishdr = hhdr; - if( size_avail == size_needed ) { - hbp = hhdr->hb_next; - hhdr = HDR(hbp); - } else { - hbp = (struct hblk *) - (((word)thishbp) + size_needed); - if (!GC_install_header(hbp)) { - hbp = thishbp; - continue; - } - hhdr = HDR(hbp); - GC_invalidate_map(hhdr); - hhdr->hb_next = thishdr->hb_next; - hhdr->hb_sz = size_avail - size_needed; - } - /* remove *thishbp from hblk freelist */ - if( prevhbp == 0 ) { - GC_hblkfreelist = hbp; - } else { - phdr->hb_next = hbp; - } - /* save current list search position */ - GC_savhbp = hbp; - break; - } - } - - /* Notify virtual dirty bit implementation that we are about to write. */ - GC_write_hint(thishbp); - - /* Add it to map of valid blocks */ - if (!GC_install_counts(thishbp, (word)size_needed)) return(0); - /* This leaks memory under very rare conditions. */ - - /* Set up header */ - if (!setup_header(thishdr, sz, kind, flags)) { - GC_remove_counts(thishbp, (word)size_needed); - return(0); /* ditto */ - } - - /* Clear block if necessary */ - if (GC_debugging_started - || sz > MAXOBJSZ && GC_obj_kinds[kind].ok_init) { - BZERO(thishbp + HDR_BYTES, size_needed - HDR_BYTES); - } - - /* We just successfully allocated a block. Restart count of */ - /* consecutive failures. */ - { - extern unsigned GC_fail_count; - - GC_fail_count = 0; - } - - return( thishbp ); -} - -struct hblk * GC_freehblk_ptr = 0; /* Search position hint for GC_freehblk */ - -/* - * Free a heap block. - * - * Coalesce the block with its neighbors if possible. - * - * All mark words are assumed to be cleared. - */ -void -GC_freehblk(p) -register struct hblk *p; -{ -register hdr *phdr; /* Header corresponding to p */ -register struct hblk *hbp, *prevhbp; -register hdr *hhdr, *prevhdr; -register signed_word size; - - /* GC_savhbp may become invalid due to coalescing. Clear it. */ - GC_savhbp = (struct hblk *)0; - - phdr = HDR(p); - size = phdr->hb_sz; - size = HBLKSIZE * OBJ_SZ_TO_BLOCKS(size); - GC_remove_counts(p, (word)size); - phdr->hb_sz = size; - GC_invalidate_map(phdr); - prevhbp = 0; - - /* The following optimization was suggested by David Detlefs. */ - /* Note that the header cannot be NIL, since there cannot be an */ - /* intervening call to GC_freehblk without resetting */ - /* GC_freehblk_ptr. */ - if (GC_freehblk_ptr != 0 && - HDR(GC_freehblk_ptr)->hb_map == GC_invalid_map && - (ptr_t)GC_freehblk_ptr < (ptr_t)p) { - hbp = GC_freehblk_ptr; - } else { - hbp = GC_hblkfreelist; - }; - hhdr = HDR(hbp); - - while( (hbp != 0) && (hbp < p) ) { - prevhbp = hbp; - prevhdr = hhdr; - hbp = hhdr->hb_next; - hhdr = HDR(hbp); - } - GC_freehblk_ptr = prevhbp; - - /* Check for duplicate deallocation in the easy case */ - if (hbp != 0 && (ptr_t)p + size > (ptr_t)hbp - || prevhbp != 0 && (ptr_t)prevhbp + prevhdr->hb_sz > (ptr_t)p) { - GC_printf1("Duplicate large block deallocation of 0x%lx\n", - (unsigned long) p); - GC_printf2("Surrounding free blocks are 0x%lx and 0x%lx\n", - (unsigned long) prevhbp, (unsigned long) hbp); - } - - /* Coalesce with successor, if possible */ - if( (((word)p)+size) == ((word)hbp) ) { - phdr->hb_next = hhdr->hb_next; - phdr->hb_sz += hhdr->hb_sz; - GC_remove_header(hbp); - } else { - phdr->hb_next = hbp; - } - - - if( prevhbp == 0 ) { - GC_hblkfreelist = p; - } else if( (((word)prevhbp) + prevhdr->hb_sz) - == ((word)p) ) { - /* Coalesce with predecessor */ - prevhdr->hb_next = phdr->hb_next; - prevhdr->hb_sz += phdr->hb_sz; - GC_remove_header(p); - } else { - prevhdr->hb_next = p; - } -} - |