GC_INNER void GC_free_inner(void * p) { struct hblk *h; hdr *hhdr; size_t sz; /* bytes */ size_t ngranules; /* sz in granules */ void ** flh; int knd; struct obj_kind * ok; DCL_LOCK_STATE; h = HBLKPTR(p); hhdr = HDR(h); knd = hhdr -> hb_obj_kind; sz = hhdr -> hb_sz; ngranules = BYTES_TO_GRANULES(sz); ok = &GC_obj_kinds[knd]; if (ngranules <= MAXOBJGRANULES) { GC_bytes_freed += sz; if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz; if (ok -> ok_init) { BZERO((word *)p + 1, sz-sizeof(word)); } flh = &(ok -> ok_freelist[ngranules]); obj_link(p) = *flh; *flh = (ptr_t)p; } else { size_t nblocks = OBJ_SZ_TO_BLOCKS(sz); GC_bytes_freed += sz; if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz; if (nblocks > 1) { GC_large_allocd_bytes -= nblocks * HBLKSIZE; } GC_freehblk(h); } }
/* * 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; }
/* Will fail to do anything if we are out of memory. */ GC_INNER void GC_new_hblk(size_t gran, int kind) { struct hblk *h; /* the new heap block */ GC_bool clear = GC_obj_kinds[kind].ok_init; GC_STATIC_ASSERT((sizeof (struct hblk)) == HBLKSIZE); if (GC_debugging_started) clear = TRUE; /* Allocate a new heap block */ h = GC_allochblk(GRANULES_TO_BYTES(gran), kind, 0); if (h == 0) return; /* Mark all objects if appropriate. */ if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h)); /* Build the free list */ GC_obj_kinds[kind].ok_freelist[gran] = GC_build_fl(h, GRANULES_TO_WORDS(gran), clear, GC_obj_kinds[kind].ok_freelist[gran]); }