/* * Generic procedure to rebuild a free list in hbp. * Also called directly from GC_malloc_many. * Sz is now in bytes. */ ptr_t GC_reclaim_generic(struct hblk * hbp, hdr *hhdr, size_t sz, GC_bool init, ptr_t list, signed_word *count) { ptr_t result = list; GC_ASSERT(GC_find_header((ptr_t)hbp) == hhdr); GC_remove_protection(hbp, 1, (hhdr)->hb_descr == 0 /* Pointer-free? */); if (init) { result = GC_reclaim_clear(hbp, hhdr, sz, list, count); } else { GC_ASSERT((hhdr)->hb_descr == 0 /* Pointer-free block */); result = GC_reclaim_uninit(hbp, hhdr, sz, list, count); } if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)) GC_set_hdr_marks(hhdr); return result; }
/* * 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); }
/* is p. */ STATIC void GC_print_type(ptr_t p) { hdr * hhdr = GC_find_header(p); char buffer[GC_TYPE_DESCR_LEN + 1]; int kind = hhdr -> hb_obj_kind; if (0 != GC_describe_type_fns[kind] && GC_is_marked(GC_base(p))) { /* This should preclude free list objects except with */ /* thread-local allocation. */ buffer[GC_TYPE_DESCR_LEN] = 0; (GC_describe_type_fns[kind])(p, buffer); GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0); GC_err_puts(buffer); } else { switch(kind) { case PTRFREE: GC_err_puts("PTRFREE"); break; case NORMAL: GC_err_puts("NORMAL"); break; case UNCOLLECTABLE: GC_err_puts("UNCOLLECTABLE"); break; # ifdef ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: GC_err_puts("ATOMIC UNCOLLECTABLE"); break; # endif case STUBBORN: GC_err_puts("STUBBORN"); break; default: GC_err_printf("kind=%d descr=0x%lx", kind, (unsigned long)(hhdr -> hb_descr)); } } }
/* p points to somewhere inside an object with the debugging info. */ STATIC void GC_print_obj(ptr_t p) { oh * ohdr = (oh *)GC_base(p); ptr_t q; hdr * hhdr; int kind; const char *kind_str; char buffer[GC_TYPE_DESCR_LEN + 1]; GC_ASSERT(I_DONT_HOLD_LOCK()); # ifdef LINT2 if (!ohdr) ABORT("Invalid GC_print_obj argument"); # endif q = (ptr_t)(ohdr + 1); /* Print a type description for the object whose client-visible */ /* address is q. */ hhdr = GC_find_header(q); kind = hhdr -> hb_obj_kind; if (0 != GC_describe_type_fns[kind] && GC_is_marked(ohdr)) { /* This should preclude free list objects except with */ /* thread-local allocation. */ buffer[GC_TYPE_DESCR_LEN] = 0; (GC_describe_type_fns[kind])(q, buffer); GC_ASSERT(buffer[GC_TYPE_DESCR_LEN] == 0); kind_str = buffer; } else { switch(kind) { case PTRFREE: kind_str = "PTRFREE"; break; case NORMAL: kind_str = "NORMAL"; break; case UNCOLLECTABLE: kind_str = "UNCOLLECTABLE"; break; # ifdef GC_ATOMIC_UNCOLLECTABLE case AUNCOLLECTABLE: kind_str = "ATOMIC_UNCOLLECTABLE"; break; # endif default: kind_str = NULL; /* The alternative is to use snprintf(buffer) but it is */ /* not quite portable (see vsnprintf in misc.c). */ } } if (NULL != kind_str) { GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") " %s)\n", (void *)((ptr_t)ohdr + sizeof(oh)), ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), kind_str); } else { GC_err_printf("%p (%s:%d," IF_NOT_SHORTDBG_HDRS(" sz=%lu,") " kind=%d descr=0x%lx)\n", (void *)((ptr_t)ohdr + sizeof(oh)), ohdr->oh_string, GET_OH_LINENUM(ohdr) /*, */ COMMA_IFNOT_SHORTDBG_HDRS((unsigned long)ohdr->oh_sz), kind, (unsigned long)hhdr->hb_descr); } PRINT_CALL_CHAIN(ohdr); }