Пример #1
0
/* The same thing, but don't clear objects: */
STATIC ptr_t GC_reclaim_uninit(struct hblk *hbp, hdr *hhdr, size_t sz,
                               ptr_t list, signed_word *count)
{
    word bit_no = 0;
    word *p, *plim;
    signed_word n_bytes_found = 0;

    GC_ASSERT(sz == hhdr -> hb_sz);
    p = (word *)(hbp->hb_body);
    plim = (word *)((ptr_t)hbp + HBLKSIZE - sz);

    /* go through all words in block */
    while (p <= plim) {
        if( !mark_bit_from_hdr(hhdr, bit_no) ) {
            n_bytes_found += sz;
            /* object is available - put on list */
            obj_link(p) = list;
            list = ((ptr_t)p);
        }
        p = (word *)((ptr_t)p + sz);
        bit_no += MARK_BIT_OFFSET(sz);
    }
    *count += n_bytes_found;
    return(list);
}
Пример #2
0
/*ARGSUSED*/
void GC_check_heap_block(struct hblk *hbp, word dummy)
{
    struct hblkhdr * hhdr = HDR(hbp);
    size_t sz = hhdr -> hb_sz;
    size_t bit_no;
    char *p, *plim;
    
    p = hbp->hb_body;
    bit_no = 0;
    if (sz > MAXOBJBYTES) {
	plim = p;
    } else {
    	plim = hbp->hb_body + HBLKSIZE - sz;
    }
    /* go through all words in block */
	while( p <= plim ) {
	    if( mark_bit_from_hdr(hhdr, bit_no)
	        && GC_HAS_DEBUG_INFO((ptr_t)p)) {
	        ptr_t clobbered = GC_check_annotated_obj((oh *)p);
	        
	        if (clobbered != 0) GC_add_smashed(clobbered);
	    }
	    bit_no += MARK_BIT_OFFSET(sz);
	    p += sz;
	}
}
Пример #3
0
/* Don't really reclaim objects, just check for unmarked ones: */
STATIC void GC_reclaim_check(struct hblk *hbp, hdr *hhdr, word sz)
{
    word bit_no;
    ptr_t p, plim;
    GC_ASSERT(sz == hhdr -> hb_sz);

    /* go through all words in block */
    p = hbp->hb_body;
    plim = p + HBLKSIZE - sz;
    for (bit_no = 0; p <= plim; p += sz, bit_no += MARK_BIT_OFFSET(sz)) {
        if (!mark_bit_from_hdr(hhdr, bit_no)) {
            GC_add_leaked(p);
        }
    }
}
Пример #4
0
/*
 * Restore unmarked small objects in h of size sz to the object
 * free list.  Returns the new list.
 * Clears unmarked objects.  Sz is in bytes.
 */
STATIC ptr_t GC_reclaim_clear(struct hblk *hbp, hdr *hhdr, size_t sz,
                              ptr_t list, signed_word *count)
{
    word bit_no = 0;
    word *p, *q, *plim;
    signed_word n_bytes_found = 0;

    GC_ASSERT(hhdr == GC_find_header((ptr_t)hbp));
    GC_ASSERT(sz == hhdr -> hb_sz);
    GC_ASSERT((sz & (BYTES_PER_WORD-1)) == 0);
    p = (word *)(hbp->hb_body);
    plim = (word *)(hbp->hb_body + HBLKSIZE - sz);

    /* go through all words in block */
    while (p <= plim) {
        if( mark_bit_from_hdr(hhdr, bit_no) ) {
            p = (word *)((ptr_t)p + sz);
        } else {
            n_bytes_found += sz;
            /* object is available - put on list */
            obj_link(p) = list;
            list = ((ptr_t)p);
            /* Clear object, advance p to next object in the process */
            q = (word *)((ptr_t)p + sz);
#                   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
        }
        bit_no += MARK_BIT_OFFSET(sz);
    }
    *count += n_bytes_found;
    return(list);
}
Пример #5
0
/* Avoid GC_apply_to_each_object for performance reasons.       */
STATIC void GC_check_heap_block(struct hblk *hbp, word dummy GC_ATTR_UNUSED)
{
    struct hblkhdr * hhdr = HDR(hbp);
    word sz = hhdr -> hb_sz;
    word bit_no;
    char *p, *plim;

    p = hbp->hb_body;
    if (sz > MAXOBJBYTES) {
      plim = p;
    } else {
      plim = hbp->hb_body + HBLKSIZE - sz;
    }
    /* go through all words in block */
    for (bit_no = 0; (word)p <= (word)plim;
         bit_no += MARK_BIT_OFFSET(sz), p += sz) {
      if (mark_bit_from_hdr(hhdr, bit_no) && GC_HAS_DEBUG_INFO((ptr_t)p)) {
        ptr_t clobbered = GC_check_annotated_obj((oh *)p);
        if (clobbered != 0)
          GC_add_smashed(clobbered);
      }
    }
}
Пример #6
0
/// The one difference between this one and the one above
/// is the addition of the flag clear.  This shouldn't really
/// matter, but I was getting a bit of weird behavior in the baseline
/// results (milc 100ms longer than previously measured) and wanted to
/// eliminate it
STATIC void HINTGC_reclaim_block(struct hblk *hbp, word report_if_found)
{
    hdr * hhdr = HDR(hbp);
    size_t sz = hhdr -> hb_sz;  /* size of objects in current block     */
    struct obj_kind * ok = &GC_obj_kinds[hhdr -> hb_obj_kind];
    struct hblk ** rlh;

    // This line added for hinted collection since we have to
    // visit every block header anyways.  Clear out the
    // pending free flags.
    hhdr->hb_flags &= ~HAS_PENDING_FREE;

    if( sz > MAXOBJBYTES ) {  /* 1 big object */
        if( !mark_bit_from_hdr(hhdr, 0) ) {
            if (report_if_found) {
                GC_add_leaked((ptr_t)hbp);
            } else {
                size_t blocks = OBJ_SZ_TO_BLOCKS(sz);
                if (blocks > 1) {
                    GC_large_allocd_bytes -= blocks * HBLKSIZE;
                }
                GC_bytes_found += sz;
                GC_freehblk(hbp);
            }
        } else {
            if (hhdr -> hb_descr != 0) {
                GC_composite_in_use += sz;
            } else {
                GC_atomic_in_use += sz;
            }
        }
    } else {
        GC_bool empty = GC_block_empty(hhdr);
#       ifdef PARALLEL_MARK
        /* Count can be low or one too high because we sometimes      */
        /* have to ignore decrements.  Objects can also potentially   */
        /* be repeatedly marked by each marker.                       */
        /* Here we assume two markers, but this is extremely          */
        /* unlikely to fail spuriously with more.  And if it does, it */
        /* should be looked at.                                       */
        GC_ASSERT(hhdr -> hb_n_marks <= 2 * (HBLKSIZE/sz + 1) + 16);
#       else
        GC_ASSERT(sz * hhdr -> hb_n_marks <= HBLKSIZE);
#       endif
        if (hhdr -> hb_descr != 0) {
            GC_composite_in_use += sz * hhdr -> hb_n_marks;
        } else {
            GC_atomic_in_use += sz * hhdr -> hb_n_marks;
        }
        if (report_if_found) {
            GC_reclaim_small_nonempty_block(hbp, TRUE /* report_if_found */);
        } else if (empty) {
            GC_bytes_found += HBLKSIZE;
            GC_freehblk(hbp);
        } else if (GC_find_leak || !GC_block_nearly_full(hhdr)) {
            /* group of smaller objects, enqueue the real work */
            rlh = &(ok -> ok_reclaim_list[BYTES_TO_GRANULES(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.                                      */
    }
}