From 96d4120ac08db3f2d566e8e5c3bc134a24aa0afc Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Mon, 2 Apr 2012 14:50:03 -0700 Subject: [PATCH] Avoid NULL check in free() and malloc_usable_size(). Generalize isalloc() to handle NULL pointers in such a way that the NULL checking overhead is only paid when introspecting huge allocations (or NULL). This allows free() and malloc_usable_size() to no longer check for NULL. Submitted by Igor Bukanov and Mike Hommey. --- Makefile.in | 2 +- .../jemalloc/internal/jemalloc_internal.h.in | 10 +++---- src/jemalloc.c | 26 ++++++++----------- test/null.c | 19 ++++++++++++++ test/null.exp | 2 ++ 5 files changed, 37 insertions(+), 22 deletions(-) create mode 100644 test/null.c create mode 100644 test/null.exp diff --git a/Makefile.in b/Makefile.in index 821c0634..d8b671ad 100644 --- a/Makefile.in +++ b/Makefile.in @@ -65,7 +65,7 @@ DOCS_HTML := $(DOCS_XML:@objroot@%.xml=@srcroot@%.html) DOCS_MAN3 := $(DOCS_XML:@objroot@%.xml=@srcroot@%.3) DOCS := $(DOCS_HTML) $(DOCS_MAN3) CTESTS := @srcroot@test/aligned_alloc.c @srcroot@test/allocated.c \ - @srcroot@test/bitmap.c @srcroot@test/mremap.c \ + @srcroot@test/bitmap.c @srcroot@test/mremap.c @srcroot@test/null.c \ @srcroot@test/posix_memalign.c @srcroot@test/thread_arena.c \ @srcroot@test/thread_tcache_enabled.c ifeq (@enable_experimental@, 1) diff --git a/include/jemalloc/internal/jemalloc_internal.h.in b/include/jemalloc/internal/jemalloc_internal.h.in index db2deb03..ed21bbe7 100644 --- a/include/jemalloc/internal/jemalloc_internal.h.in +++ b/include/jemalloc/internal/jemalloc_internal.h.in @@ -633,8 +633,6 @@ isalloc(const void *ptr) size_t ret; arena_chunk_t *chunk; - assert(ptr != NULL); - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) { /* Region. */ @@ -642,8 +640,10 @@ isalloc(const void *ptr) ret = arena_salloc_demote(ptr); else ret = arena_salloc(ptr); - } else + } else if (ptr != NULL) ret = huge_salloc(ptr); + else + ret = 0; return (ret); } @@ -664,12 +664,10 @@ idalloc(void *ptr) { arena_chunk_t *chunk; - assert(ptr != NULL); - chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); if (chunk != ptr) arena_dalloc(chunk->arena, chunk, ptr); - else + else if (ptr != NULL) huge_dalloc(ptr, true); } diff --git a/src/jemalloc.c b/src/jemalloc.c index 1deabcd9..86ce695b 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -1100,22 +1100,18 @@ JEMALLOC_ATTR(visibility("default")) void je_free(void *ptr) { + size_t usize; - if (ptr != NULL) { - size_t usize; + assert(malloc_initialized || IS_INITIALIZER); - assert(malloc_initialized || IS_INITIALIZER); - - if (config_prof && opt_prof) { - usize = isalloc(ptr); - prof_free(ptr, usize); - } else if (config_stats) { - usize = isalloc(ptr); - } - if (config_stats) - thread_allocated_tsd_get()->deallocated += usize; - idalloc(ptr); - } + if (config_prof && opt_prof) { + usize = isalloc(ptr); + prof_free(ptr, usize); + } else if (config_stats) + usize = isalloc(ptr); + if (config_stats) + thread_allocated_tsd_get()->deallocated += usize; + idalloc(ptr); } /* @@ -1200,7 +1196,7 @@ je_malloc_usable_size(const void *ptr) if (config_ivsalloc) ret = ivsalloc(ptr); else - ret = (ptr != NULL) ? isalloc(ptr) : 0; + ret = isalloc(ptr); return (ret); } diff --git a/test/null.c b/test/null.c new file mode 100644 index 00000000..ccd7ced3 --- /dev/null +++ b/test/null.c @@ -0,0 +1,19 @@ +#include +#include + +#define JEMALLOC_MANGLE +#include "jemalloc_test.h" + +int +main(void) +{ + + fprintf(stderr, "Test begin\n"); + + free(malloc(1)); + free(NULL); + assert(malloc_usable_size(NULL) == 0); + + fprintf(stderr, "Test end\n"); + return (0); +} diff --git a/test/null.exp b/test/null.exp new file mode 100644 index 00000000..369a88dd --- /dev/null +++ b/test/null.exp @@ -0,0 +1,2 @@ +Test begin +Test end