summaryrefslogtreecommitdiff
path: root/malloc.c
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2023-01-18 07:47:49 +0300
committerIvan Maidanski <ivmai@mail.ru>2023-01-18 07:47:49 +0300
commit6ed8630b91f1d21598a069db6bbb7a072bc44915 (patch)
treedce2e9dc5daadffef45d7ec9801569a981ff4b22 /malloc.c
parent25aa62fee7b13902e4f0fbef3e42db22325a7614 (diff)
downloadbdwgc-6ed8630b91f1d21598a069db6bbb7a072bc44915.tar.gz
Remove code duplication in GC_free[_inner]
(refactoring) * include/private/gc_priv.h [THREADS] (GC_free_inner): Move comment from malloc.c. * malloc.c (free_internal): New static function (move code from GC_free_inner but with several changes - remove h and nblocks local variables, move hhdr to arguments, specify ngranules <= MAXOBJGRANULES as likely, remove code duplication). * malloc.c (GC_free): Use free_internal(); remove h, sz, ngranules, knd, ok local variables. * malloc.c [THREADS] (GC_free_inner): Likewise. * malloc.c [REDIRECT_MALLOC && (GC_SOLARIS_THREADS || GC_LINUX_THREADS || NEED_CALLINFO && GC_HAVE_BUILTIN_BACKTRACE || MSWIN32)] (GC_free): Specify hhdr==0 as unlikely.
Diffstat (limited to 'malloc.c')
-rw-r--r--malloc.c114
1 files changed, 37 insertions, 77 deletions
diff --git a/malloc.c b/malloc.c
index fc5dc4be..8d3fae06 100644
--- a/malloc.c
+++ b/malloc.c
@@ -560,15 +560,40 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_malloc_uncollectable(size_t lb)
#endif /* REDIRECT_MALLOC */
-/* Explicitly deallocate an object p. */
+/* Explicitly deallocate the object. hhdr should correspond to p. */
+static void free_internal(void *p, hdr *hhdr)
+{
+ size_t sz = (size_t)(hhdr -> hb_sz); /* in bytes */
+ size_t ngranules = BYTES_TO_GRANULES(sz); /* size in granules */
+ int knd = hhdr -> hb_obj_kind;
+
+ GC_bytes_freed += sz;
+ if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz;
+ if (EXPECT(ngranules <= MAXOBJGRANULES, TRUE)) {
+ struct obj_kind *ok = &GC_obj_kinds[knd];
+ void **flh;
+
+ /* It is unnecessary to clear the mark bit. If the object is */
+ /* reallocated, it does not matter. Otherwise, the collector will */
+ /* do it, since it is on a free list. */
+ if (ok -> ok_init && EXPECT(sz > sizeof(word), TRUE)) {
+ BZERO((word *)p + 1, sz - sizeof(word));
+ }
+
+ flh = &(ok -> ok_freelist[ngranules]);
+ obj_link(p) = *flh;
+ *flh = (ptr_t)p;
+ } else {
+ if (sz > HBLKSIZE) {
+ GC_large_allocd_bytes -= HBLKSIZE * OBJ_SZ_TO_BLOCKS(sz);
+ }
+ GC_freehblk(HBLKPTR(p));
+ }
+}
+
GC_API void GC_CALL GC_free(void * p)
{
- struct hblk *h;
hdr *hhdr;
- size_t sz; /* In bytes */
- size_t ngranules; /* sz in granules */
- int knd;
- struct obj_kind * ok;
DCL_LOCK_STATE;
if (p /* != NULL */) {
@@ -582,8 +607,7 @@ GC_API void GC_CALL GC_free(void * p)
GC_log_printf("GC_free(%p) after GC #%lu\n",
p, (unsigned long)GC_gc_no);
# endif
- h = HBLKPTR(p);
- hhdr = HDR(h);
+ hhdr = HDR(p);
# if defined(REDIRECT_MALLOC) && \
((defined(NEED_CALLINFO) && defined(GC_HAVE_BUILTIN_BACKTRACE)) \
|| defined(GC_SOLARIS_THREADS) || defined(GC_LINUX_THREADS) \
@@ -594,83 +618,19 @@ GC_API void GC_CALL GC_free(void * p)
/* initialization. For the others, this seems to happen */
/* implicitly. */
/* Don't try to deallocate that memory. */
- if (0 == hhdr) return;
+ if (EXPECT(NULL == hhdr, FALSE)) return;
# endif
GC_ASSERT(GC_base(p) == p);
- sz = (size_t)hhdr->hb_sz;
- ngranules = BYTES_TO_GRANULES(sz);
- knd = hhdr -> hb_obj_kind;
- ok = &GC_obj_kinds[knd];
- if (EXPECT(ngranules <= MAXOBJGRANULES, TRUE)) {
- void **flh;
-
- LOCK();
- GC_bytes_freed += sz;
- if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz;
- /* It's unnecessary to clear the mark bit. If the */
- /* object is reallocated, it doesn't matter. O.w. the */
- /* collector will do it, since it's on a free list. */
- if (ok -> ok_init && EXPECT(sz > sizeof(word), TRUE)) {
- BZERO((word *)p + 1, sz-sizeof(word));
- }
- flh = &(ok -> ok_freelist[ngranules]);
- obj_link(p) = *flh;
- *flh = (ptr_t)p;
- UNLOCK();
- } else {
- size_t nblocks = OBJ_SZ_TO_BLOCKS(sz);
-
- LOCK();
- 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);
- UNLOCK();
- }
+ LOCK();
+ free_internal(p, hhdr);
+ UNLOCK();
}
-/* Explicitly deallocate an object p when we already hold lock. */
-/* Only used for internally allocated objects, so we can take some */
-/* shortcuts. */
#ifdef THREADS
GC_INNER void GC_free_inner(void * p)
{
- struct hblk *h;
- hdr *hhdr;
- size_t sz; /* bytes */
- size_t ngranules; /* sz in granules */
- int knd;
- struct obj_kind * ok;
-
GC_ASSERT(I_HOLD_LOCK());
- h = HBLKPTR(p);
- hhdr = HDR(h);
- knd = hhdr -> hb_obj_kind;
- sz = (size_t)hhdr->hb_sz;
- ngranules = BYTES_TO_GRANULES(sz);
- ok = &GC_obj_kinds[knd];
- if (ngranules <= MAXOBJGRANULES) {
- void ** flh;
-
- GC_bytes_freed += sz;
- if (IS_UNCOLLECTABLE(knd)) GC_non_gc_bytes -= sz;
- if (ok -> ok_init && EXPECT(sz > sizeof(word), TRUE)) {
- 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);
- }
+ free_internal(p, HDR(p));
}
#endif /* THREADS */