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.
This commit is contained in:
Jason Evans 2012-04-02 14:50:03 -07:00
parent 80b25932ca
commit 96d4120ac0
5 changed files with 37 additions and 22 deletions

View File

@ -65,7 +65,7 @@ DOCS_HTML := $(DOCS_XML:@objroot@%.xml=@srcroot@%.html)
DOCS_MAN3 := $(DOCS_XML:@objroot@%.xml=@srcroot@%.3) DOCS_MAN3 := $(DOCS_XML:@objroot@%.xml=@srcroot@%.3)
DOCS := $(DOCS_HTML) $(DOCS_MAN3) DOCS := $(DOCS_HTML) $(DOCS_MAN3)
CTESTS := @srcroot@test/aligned_alloc.c @srcroot@test/allocated.c \ 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/posix_memalign.c @srcroot@test/thread_arena.c \
@srcroot@test/thread_tcache_enabled.c @srcroot@test/thread_tcache_enabled.c
ifeq (@enable_experimental@, 1) ifeq (@enable_experimental@, 1)

View File

@ -633,8 +633,6 @@ isalloc(const void *ptr)
size_t ret; size_t ret;
arena_chunk_t *chunk; arena_chunk_t *chunk;
assert(ptr != NULL);
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
if (chunk != ptr) { if (chunk != ptr) {
/* Region. */ /* Region. */
@ -642,8 +640,10 @@ isalloc(const void *ptr)
ret = arena_salloc_demote(ptr); ret = arena_salloc_demote(ptr);
else else
ret = arena_salloc(ptr); ret = arena_salloc(ptr);
} else } else if (ptr != NULL)
ret = huge_salloc(ptr); ret = huge_salloc(ptr);
else
ret = 0;
return (ret); return (ret);
} }
@ -664,12 +664,10 @@ idalloc(void *ptr)
{ {
arena_chunk_t *chunk; arena_chunk_t *chunk;
assert(ptr != NULL);
chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
if (chunk != ptr) if (chunk != ptr)
arena_dalloc(chunk->arena, chunk, ptr); arena_dalloc(chunk->arena, chunk, ptr);
else else if (ptr != NULL)
huge_dalloc(ptr, true); huge_dalloc(ptr, true);
} }

View File

@ -1100,8 +1100,6 @@ JEMALLOC_ATTR(visibility("default"))
void void
je_free(void *ptr) je_free(void *ptr)
{ {
if (ptr != NULL) {
size_t usize; size_t usize;
assert(malloc_initialized || IS_INITIALIZER); assert(malloc_initialized || IS_INITIALIZER);
@ -1109,13 +1107,11 @@ je_free(void *ptr)
if (config_prof && opt_prof) { if (config_prof && opt_prof) {
usize = isalloc(ptr); usize = isalloc(ptr);
prof_free(ptr, usize); prof_free(ptr, usize);
} else if (config_stats) { } else if (config_stats)
usize = isalloc(ptr); usize = isalloc(ptr);
}
if (config_stats) if (config_stats)
thread_allocated_tsd_get()->deallocated += usize; thread_allocated_tsd_get()->deallocated += usize;
idalloc(ptr); idalloc(ptr);
}
} }
/* /*
@ -1200,7 +1196,7 @@ je_malloc_usable_size(const void *ptr)
if (config_ivsalloc) if (config_ivsalloc)
ret = ivsalloc(ptr); ret = ivsalloc(ptr);
else else
ret = (ptr != NULL) ? isalloc(ptr) : 0; ret = isalloc(ptr);
return (ret); return (ret);
} }

19
test/null.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
#include <assert.h>
#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);
}

2
test/null.exp Normal file
View File

@ -0,0 +1,2 @@
Test begin
Test end