Bug 422960: Add jemalloc_stats() and jemalloc.h, r=benjamin

This commit is contained in:
Jason Evans 2008-06-20 10:34:42 -07:00
Родитель 2bbdb5cee1
Коммит d1e7b47846
5 изменённых файлов: 234 добавлений и 79 удалений

Просмотреть файл

@ -359,6 +359,12 @@ LDFLAGS += -lposix4 -ldl -lnsl -lsocket
endif
endif
ifdef MOZ_MEMORY
ifeq ($(OS_ARCH),Darwin)
LDFLAGS += -ljemalloc
endif
endif
# Allow building jsinterp.c with special optimization flags
ifdef INTERP_OPTIMIZER
jsinterp.$(OBJ_SUFFIX): MODULE_OPTIMIZE_FLAGS=$(INTERP_OPTIMIZER)

Просмотреть файл

@ -88,14 +88,12 @@
#endif
/*
* jemalloc provides posix_memalign but the function has to be explicitly
* declared on Windows.
* jemalloc provides posix_memalign.
*/
#if HAS_POSIX_MEMALIGN && MOZ_MEMORY_WINDOWS
JS_BEGIN_EXTERN_C
extern int
posix_memalign(void **memptr, size_t alignment, size_t size);
JS_END_EXTERN_C
#ifdef MOZ_MEMORY
extern "C" {
#include "../../memory/jemalloc/jemalloc.h"
}
#endif
/*

Просмотреть файл

@ -45,6 +45,10 @@ include $(DEPTH)/config/autoconf.mk
MODULE = jemalloc
# jemalloc.c properly uses 'static', so don't burden it with manually exposing
# symbols.
VISIBILITY_FLAGS=
ifeq (WINNT,$(OS_TARGET))
# Two options for Windows, either you build the CRT from source,
# or you use a pre-built DLL.
@ -68,8 +72,9 @@ $(CRT_OBJ_DIR)/jemalloc.c: $(srcdir)/crtsp1.diff
$(CRT_OBJ_DIR) $(srcdir)/ed.exe
$(CRT_OBJ_DIR)/build/intel/mozcrt19.dll: \
$(CRT_OBJ_DIR)/jemalloc.c $(srcdir)/jemalloc.c $(srcdir)/tree.h
cp $(srcdir)/jemalloc.c $(srcdir)/tree.h $(CRT_OBJ_DIR)
$(CRT_OBJ_DIR)/jemalloc.c $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h \
$(srcdir)/tree.h
cp $(srcdir)/jemalloc.c $(srcdir)/jemalloc.h $(srcdir)/tree.h $(CRT_OBJ_DIR)
# this pretty much sucks, but nmake and make don't play well together
$(PYTHON) $(srcdir)/build-crt.py $(CRT_OBJ_DIR)
#XXX: these don't link right for some reason

Просмотреть файл

@ -103,6 +103,12 @@
# define MALLOC_PRODUCTION
#endif
/*
* MALLOC_STATS enables statistics calculation, and is required for
* jemalloc_stats().
*/
#define MALLOC_STATS
#ifndef MALLOC_PRODUCTION
/*
* MALLOC_DEBUG enables assertions and other sanity checks, and disables
@ -110,9 +116,6 @@
*/
# define MALLOC_DEBUG
/* MALLOC_STATS enables statistics calculation. */
# define MALLOC_STATS
/* Memory filling (junk/zero). */
# define MALLOC_FILL
@ -203,7 +206,6 @@
#pragma warning( disable: 4267 4996 4146 )
#define bool BOOL
#define false FALSE
#define true TRUE
#define inline __inline
@ -336,6 +338,8 @@ __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 179704 2008-06-10 15:46:18Z ja
#endif
#include "jemalloc.h"
#ifdef MOZ_MEMORY_DARWIN
static const bool __isthreaded = true;
#endif
@ -364,12 +368,6 @@ static const bool __isthreaded = true;
# define inline
#endif
#ifdef __GNUC__
#define VISIBLE __attribute__((visibility("default")))
#else
#define VISIBLE
#endif
/* Size of stack-allocated buffer passed to strerror_r(). */
#define STRERROR_BUF 64
@ -1119,7 +1117,7 @@ static void wrtmessage(const char *p1, const char *p2, const char *p3,
#ifdef MALLOC_STATS
#ifdef MOZ_MEMORY_DARWIN
/* Avoid namespace collision with OS X's malloc APIs. */
#define malloc_printf xmalloc_printf
#define malloc_printf moz_malloc_printf
#endif
static void malloc_printf(const char *format, ...);
#endif
@ -5735,14 +5733,28 @@ malloc_shutdown()
* Begin malloc(3)-compatible functions.
*/
VISIBLE
/*
* Inline the standard malloc functions if they are being subsumed by Darwin's
* zone infrastructure.
*/
#ifdef MOZ_MEMORY_DARWIN
inline void *
moz_malloc(size_t size)
# define ZONE_INLINE inline
#else
# define ZONE_INLINE
#endif
/* Mangle standard interfaces on Darwin, in order to avoid linking problems. */
#ifdef MOZ_MEMORY_DARWIN
#define malloc(a) moz_malloc(a)
#define valloc(a) moz_valloc(a)
#define calloc(a, b) moz_calloc(a, b)
#define realloc(a, b) moz_realloc(a, b)
#define free(a) moz_free(a)
#endif
ZONE_INLINE
void *
malloc(size_t size)
#endif
{
void *ret;
@ -5783,26 +5795,19 @@ RETURN:
return (ret);
}
#ifdef MOZ_MEMORY_DARWIN
VISIBLE
inline void *
moz_memalign(size_t alignment, size_t size)
#elif (defined(MOZ_MEMORY_SOLARIS))
#ifdef MOZ_MEMORY_SOLARIS
# ifdef __SUNPRO_C
void *
memalign(size_t alignment, size_t size);
#pragma no_inline(memalign)
# elif (defined(__GNU_C__)
# elif (defined(__GNU_C__))
__attribute__((noinline))
# endif
VISIBLE
#else
inline
#endif
void *
memalign(size_t alignment, size_t size)
#else
VISIBLE
inline void *
memalign(size_t alignment, size_t size)
#endif
{
void *ret;
@ -5828,14 +5833,9 @@ RETURN:
return (ret);
}
VISIBLE
#ifdef MOZ_MEMORY_DARWIN
inline int
moz_posix_memalign(void **memptr, size_t alignment, size_t size)
#else
ZONE_INLINE
int
posix_memalign(void **memptr, size_t alignment, size_t size)
#endif
{
void *result;
@ -5864,14 +5864,9 @@ posix_memalign(void **memptr, size_t alignment, size_t size)
return (0);
}
VISIBLE
#ifdef MOZ_MEMORY_DARWIN
inline void *
moz_valloc(size_t size)
#else
ZONE_INLINE
void *
valloc(size_t size)
#endif
{
#ifdef MOZ_MEMORY_DARWIN
return (moz_memalign(pagesize, size));
@ -5880,14 +5875,9 @@ valloc(size_t size)
#endif
}
VISIBLE
#ifdef MOZ_MEMORY_DARWIN
inline void *
moz_calloc(size_t num, size_t size)
#else
ZONE_INLINE
void *
calloc(size_t num, size_t size)
#endif
{
void *ret;
size_t num_size;
@ -5941,14 +5931,9 @@ RETURN:
return (ret);
}
VISIBLE
#ifdef MOZ_MEMORY_DARWIN
inline void *
moz_realloc(void *ptr, size_t size)
#else
ZONE_INLINE
void *
realloc(void *ptr, size_t size)
#endif
{
void *ret;
@ -6009,14 +5994,9 @@ RETURN:
return (ret);
}
VISIBLE
#ifdef MOZ_MEMORY_DARWIN
inline void
moz_free(void *ptr)
#else
ZONE_INLINE
void
free(void *ptr)
#endif
{
UTRACE(ptr, 0, 0);
@ -6035,14 +6015,8 @@ free(void *ptr)
* Begin non-standard functions.
*/
VISIBLE
#ifdef MOZ_MEMORY_DARWIN
inline size_t
moz_malloc_usable_size(const void *ptr)
#else
size_t
malloc_usable_size(const void *ptr)
#endif
{
#ifdef MALLOC_VALIDATE
@ -6054,6 +6028,121 @@ malloc_usable_size(const void *ptr)
#endif
}
void
jemalloc_stats(jemalloc_stats_t *stats)
{
size_t i;
assert(stats != NULL);
/*
* Gather runtime settings.
*/
stats->opt_abort = opt_abort;
stats->opt_dss =
#ifdef MALLOC_DSS
opt_dss ? true :
#endif
false;
stats->opt_junk =
#ifdef MALLOC_FILL
opt_junk ? true :
#endif
false;
stats->opt_mmap =
#ifdef MALLOC_DSS
opt_mmap == false ? false :
#endif
true;
stats->opt_utrace =
#ifdef MALLOC_UTRACE
opt_utrace ? true :
#endif
false;
stats->opt_sysv =
#ifdef MALLOC_SYSV
opt_sysv ? true :
#endif
false;
stats->opt_xmalloc =
#ifdef MALLOC_XMALLOC
opt_xmalloc ? true :
#endif
false;
stats->opt_zero =
#ifdef MALLOC_FILL
opt_zero ? true :
#endif
false;
stats->narenas = narenas;
stats->balance_threshold =
#ifdef MALLOC_BALANCE
opt_balance_threshold
#else
SIZE_T_MAX
#endif
;
stats->quantum = quantum;
stats->small_max = small_max;
stats->large_max = arena_maxclass;
stats->chunksize = chunksize;
stats->dirty_max = opt_dirty_max;
/*
* Gather current memory usage statistics.
*/
stats->mapped = 0;
stats->committed = 0;
stats->allocated = 0;
stats->dirty = 0;
/* Get huge mapped/allocated. */
malloc_mutex_lock(&huge_mtx);
stats->mapped += stats_chunks.curchunks * chunksize;
#ifdef MALLOC_DECOMMIT
stats->committed += huge_allocated;
#endif
stats->allocated += huge_allocated;
malloc_mutex_unlock(&huge_mtx);
/* Get base mapped. */
malloc_mutex_lock(&base_mtx);
stats->mapped += base_mapped;
#ifdef MALLOC_DECOMMIT
stats->committed += base_mapped;
#endif
malloc_mutex_unlock(&base_mtx);
/* Iterate over arenas and their chunks. */
for (i = 0; i < narenas; i++) {
arena_t *arena = arenas[i];
if (arena != NULL) {
arena_chunk_t *chunk;
malloc_spin_lock(&arena->lock);
stats->allocated += arena->stats.allocated_small;
stats->allocated += arena->stats.allocated_large;
#ifdef MALLOC_DECOMMIT
RB_FOREACH(chunk, arena_chunk_tree_s, &arena->chunks) {
size_t j;
for (j = 0; j < chunk_npages; j++) {
if ((chunk->map[j] &
CHUNK_MAP_DECOMMITTED) == 0)
stats->committed += pagesize;
}
}
#endif
stats->dirty += (arena->ndirty << pagesize_2pow);
malloc_spin_unlock(&arena->lock);
}
}
#ifndef MALLOC_DECOMMIT
stats->committed = stats->mapped;
#endif
}
#ifdef MOZ_MEMORY_WINDOWS
void*
_recalloc(void *ptr, size_t count, size_t size)
@ -6187,14 +6276,14 @@ static void *
zone_malloc(malloc_zone_t *zone, size_t size)
{
return (moz_malloc(size));
return (malloc(size));
}
static void *
zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
{
return (moz_calloc(num, size));
return (calloc(num, size));
}
static void *
@ -6202,7 +6291,7 @@ zone_valloc(malloc_zone_t *zone, size_t size)
{
void *ret = NULL; /* Assignment avoids useless compiler warning. */
moz_posix_memalign(&ret, pagesize, size);
posix_memalign(&ret, pagesize, size);
return (ret);
}
@ -6211,14 +6300,14 @@ static void
zone_free(malloc_zone_t *zone, void *ptr)
{
moz_free(ptr);
free(ptr);
}
static void *
zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
{
return (moz_realloc(ptr, size));
return (realloc(ptr, size));
}
static void *
@ -6241,10 +6330,10 @@ zone_good_size(malloc_zone_t *zone, size_t size)
* how large it could have been without moving up to the next size
* class.
*/
p = moz_malloc(size);
p = malloc(size);
if (p != NULL) {
ret = isalloc(p);
moz_free(p);
free(p);
} else
ret = size;

Просмотреть файл

@ -0,0 +1,57 @@
#ifndef MOZ_MEMORY_WINDOWS
# include <stdbool.h>
#else
# include <windows.h>
# ifndef bool
# define bool BOOL
# endif
#endif
extern const char *_malloc_options;
/*
* jemalloc_stats() is not a stable interface. When using jemalloc_stats_t, be
* sure that the compiled results of jemalloc.c are in sync with this header
* file.
*/
typedef struct {
/*
* Run-time configuration settings.
*/
bool opt_abort; /* abort(3) on error? */
bool opt_dss; /* Use sbrk(2) to map memory? */
bool opt_junk; /* Fill allocated/free memory with 0xa5/0x5a? */
bool opt_mmap; /* Use mmap(2) to map memory? */
bool opt_utrace; /* Trace all allocation events? */
bool opt_sysv; /* SysV semantics? */
bool opt_xmalloc; /* abort(3) on OOM? */
bool opt_zero; /* Fill allocated memory with 0x0? */
size_t narenas; /* Number of arenas. */
size_t balance_threshold; /* Arena contention rebalance threshold. */
size_t quantum; /* Allocation quantum. */
size_t small_max; /* Max quantum-spaced allocation size. */
size_t large_max; /* Max sub-chunksize allocation size. */
size_t chunksize; /* Size of each virtual memory mapping. */
size_t dirty_max; /* Max dirty pages per arena. */
/*
* Current memory usage statistics.
*/
size_t mapped; /* Bytes mapped (not necessarily committed). */
size_t committed; /* Bytes committed (readable/writable). */
size_t allocated; /* Bytes allocted (in use by application). */
size_t dirty; /* Bytes dirty (committed unused pages). */
} jemalloc_stats_t;
#ifndef MOZ_MEMORY_DARWIN
void *malloc(size_t size);
void *valloc(size_t size);
void *calloc(size_t num, size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
#endif
int posix_memalign(void **memptr, size_t alignment, size_t size);
void *memalign(size_t alignment, size_t size);
size_t malloc_usable_size(const void *ptr);
void jemalloc_stats(jemalloc_stats_t *stats);