Regenerate files and re-add android changes.

Update to the jemalloc top of tree and regenerate all of the files
using configure.

Also, re-add all of small the android changes.

In addition, add a new define to allow the chunk size to be changed
easily. Use this define to set the chunk size to 512K for the 32 bit
library, and set the chunk size to 2MB for the 64 bit library.

Bug: 23633724
Change-Id: I9daef0428e6c22e56eb7b05089f9a3f6e2f86d82
diff --git a/Android.mk b/Android.mk
index d49af86..60d0ae3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -39,6 +39,10 @@
 #     then large allocations will take longer to complete.
 #   ANDROID_LG_TCACHE_MAXCLASS_DEFAULT=XX
 #     1 << XX is the maximum sized allocation that will be in the tcache.
+#   ANDROID_LG_CHUNK_DEFAULT=XX
+#     1 << XX is the default chunk size used by the system. Decreasing this
+#     usually decreases the amount of PSS used, but can increase
+#     fragmentation.
 jemalloc_common_cflags += \
 	-DANDROID_ALWAYS_PURGE \
 	-DANDROID_MAX_ARENAS=2 \
@@ -46,6 +50,17 @@
 	-DANDROID_TCACHE_NSLOTS_LARGE=16 \
 	-DANDROID_LG_TCACHE_MAXCLASS_DEFAULT=16 \
 
+# Use a 512K chunk size on 32 bit systems.
+# This keeps the total amount of virtual address space consumed
+# by jemalloc lower.
+jemalloc_common_cflags_32 += \
+	-DANDROID_LG_CHUNK_DEFAULT=19 \
+
+# Use a 2MB chunk size on 64 bit systems.
+# This is the default currently used by 4.0.0.
+jemalloc_common_cflags_64 += \
+	-DANDROID_LG_CHUNK_DEFAULT=21 \
+
 jemalloc_common_c_includes := \
 	$(LOCAL_PATH)/src \
 	$(LOCAL_PATH)/include \
@@ -66,6 +81,7 @@
 	src/jemalloc.c \
 	src/mb.c \
 	src/mutex.c \
+	src/pages.c \
 	src/prof.c \
 	src/quarantine.c \
 	src/rtree.c \
@@ -89,6 +105,9 @@
 	$(jemalloc_common_cflags) \
 	-include bionic/libc/private/libc_logging.h \
 
+LOCAL_CFLAGS_32 := $(jemalloc_common_cflags_32)
+LOCAL_CFLAGS_64 := $(jemalloc_common_cflags_64)
+
 LOCAL_C_INCLUDES := \
 	$(jemalloc_common_c_includes) \
 
@@ -116,6 +135,9 @@
 	-DJEMALLOC_JET \
 	-include $(LOCAL_PATH)/android/include/libc_logging.h \
 
+LOCAL_CFLAGS_32 := $(jemalloc_common_cflags_32)
+LOCAL_CFLAGS_64 := $(jemalloc_common_cflags_64)
+
 LOCAL_C_INCLUDES := \
 	$(jemalloc_common_c_includes) \
 
@@ -129,6 +151,7 @@
 	test/src/btalloc_0.c \
 	test/src/btalloc_1.c \
 	test/src/math.c \
+	test/src/mq.c \
 	test/src/mtx.c \
 	test/src/SFMT.c \
 	test/src/test.c \
@@ -151,6 +174,9 @@
 	-DJEMALLOC_UNIT_TEST \
 	-include $(LOCAL_PATH)/android/include/libc_logging.h \
 
+LOCAL_CFLAGS_32 := $(jemalloc_common_cflags_32)
+LOCAL_CFLAGS_64 := $(jemalloc_common_cflags_64)
+
 LOCAL_C_INCLUDES := \
 	$(jemalloc_common_c_includes) \
 	$(LOCAL_PATH)/test/src \
@@ -161,6 +187,7 @@
 LOCAL_WHOLE_STATIC_LIBRARIES := libjemalloc_jet
 
 include $(BUILD_STATIC_LIBRARY)
+#include $(BUILD_SHARED_LIBRARY)
 
 #-----------------------------------------------------------------------
 # jemalloc unit tests
@@ -179,6 +206,7 @@
 	test/unit/mq.c \
 	test/unit/mtx.c \
 	test/unit/prof_accum.c \
+	test/unit/prof_active.c \
 	test/unit/prof_gdump.c \
 	test/unit/prof_idump.c \
 	test/unit/prof_reset.c \
@@ -220,6 +248,9 @@
 	-DJEMALLOC_INTEGRATION_TEST \
 	-include $(LOCAL_PATH)/android/include/libc_logging.h \
 
+LOCAL_CFLAGS_32 := $(jemalloc_common_cflags_32)
+LOCAL_CFLAGS_64 := $(jemalloc_common_cflags_64)
+
 LOCAL_C_INCLUDES := \
 	$(jemalloc_common_c_includes) \
 	$(LOCAL_PATH)/test/src \
@@ -237,15 +268,16 @@
 jemalloc_integration_tests := \
 	test/integration/aligned_alloc.c \
 	test/integration/allocated.c \
-	test/integration/sdallocx.c \
-	test/integration/mallocx.c \
+	test/integration/chunk.c \
 	test/integration/MALLOCX_ARENA.c \
+	test/integration/mallocx.c \
+	test/integration/overflow.c \
 	test/integration/posix_memalign.c \
 	test/integration/rallocx.c \
+	test/integration/sdallocx.c \
 	test/integration/thread_arena.c \
 	test/integration/thread_tcache_enabled.c \
 	test/integration/xallocx.c \
-	test/integration/chunk.c \
 
 $(foreach test,$(jemalloc_integration_tests), \
   $(eval test_name := $(basename $(notdir $(test)))); \
diff --git a/android/scripts/conf_arm.sh b/android/scripts/conf_arm.sh
index a844182..6b694af 100755
--- a/android/scripts/conf_arm.sh
+++ b/android/scripts/conf_arm.sh
@@ -17,7 +17,6 @@
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libc/kernel/uapi/asm-arm"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include/arm"
-  "-include ${ANDROID_BUILD_TOP}/build/core/combo/include/arch/linux-arm/AndroidConfig.h"
 )
 
 # Copy libm.so to libpthread.so to allow -lpthread to work.
diff --git a/android/scripts/conf_arm64.sh b/android/scripts/conf_arm64.sh
index 83cffd9..ad9b53c 100755
--- a/android/scripts/conf_arm64.sh
+++ b/android/scripts/conf_arm64.sh
@@ -17,7 +17,6 @@
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libc/kernel/uapi/asm-arm64"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include/arm64"
-  "-include ${ANDROID_BUILD_TOP}/build/core/combo/include/arch/linux-arm64/AndroidConfig.h"
 )
 
 # Copy libm.so to libpthread.so to allow -lpthread to work.
diff --git a/android/scripts/conf_mips.sh b/android/scripts/conf_mips.sh
index 17f43dc..17ed3ee 100755
--- a/android/scripts/conf_mips.sh
+++ b/android/scripts/conf_mips.sh
@@ -17,7 +17,6 @@
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libc/kernel/uapi/asm-mips"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include/mips"
-  "-include ${ANDROID_BUILD_TOP}/build/core/combo/include/arch/linux-mips/AndroidConfig.h"
 )
 
 # Copy libm.so to libpthread.so to allow -lpthread to work.
diff --git a/android/scripts/conf_x86.sh b/android/scripts/conf_x86.sh
index 5b7b468..fe200eb 100755
--- a/android/scripts/conf_x86.sh
+++ b/android/scripts/conf_x86.sh
@@ -17,7 +17,6 @@
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libc/kernel/uapi/asm-x86"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include/i387"
-  "-include ${ANDROID_BUILD_TOP}/build/core/combo/include/arch/linux-x86/AndroidConfig.h"
 )
 
 # Copy libm.so to libpthread.so to allow -lpthread to work.
diff --git a/android/scripts/conf_x86_64.sh b/android/scripts/conf_x86_64.sh
index a0a2ca1..2acf41a 100755
--- a/android/scripts/conf_x86_64.sh
+++ b/android/scripts/conf_x86_64.sh
@@ -17,7 +17,6 @@
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libc/kernel/uapi/asm-x86"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include"
   "-isystem ${ANDROID_BUILD_TOP}/bionic/libm/include/amd64"
-  "-include ${ANDROID_BUILD_TOP}/build/core/combo/include/arch/linux-x86/AndroidConfig.h"
 )
 
 # Copy libm.so to libpthread.so to allow -lpthread to work.
diff --git a/android/test/run_jemalloc_tests.sh b/android/test/run_jemalloc_tests.sh
index 58698ca..75670f4 100755
--- a/android/test/run_jemalloc_tests.sh
+++ b/android/test/run_jemalloc_tests.sh
@@ -30,6 +30,7 @@
   "mq" \
   "mtx" \
   "prof_accum" \
+  "prof_active" \
   "prof_gdump" \
   "prof_idump" \
   "prof_reset" \
@@ -52,15 +53,16 @@
 INTEGRATION_TESTS=( \
   "aligned_alloc" \
   "allocated" \
-  "sdallocx" \
-  "mallocx" \
+  "chunk" \
   "MALLOCX_ARENA" \
+  "mallocx" \
+  "overflow" \
   "posix_memalign" \
   "rallocx" \
+  "sdallocx" \
   "thread_arena" \
   "thread_tcache_enabled" \
   "xallocx" \
-  "chunk" \
 )
 
 TEST_DIRECTORIES=( "/data/nativetest" "/data/nativetest64" )
diff --git a/include/jemalloc/internal/arena.h b/include/jemalloc/internal/arena.h
index 4c1a471..6041d95 100644
--- a/include/jemalloc/internal/arena.h
+++ b/include/jemalloc/internal/arena.h
@@ -1230,8 +1230,20 @@
 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
 	if (likely(chunk != ptr)) {
 		pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
+#if defined(__ANDROID__)
+		/* Verify the ptr is actually in the chunk. */
+		if (unlikely(pageind < map_bias || pageind >= chunk_npages)) {
+		    __libc_fatal("Invalid address %p passed to free: invalid page index", ptr);
+		}
+#endif
 		mapbits = arena_mapbits_get(chunk, pageind);
 		assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
+#if defined(__ANDROID__)
+		/* Verify the ptr has been allocated. */
+		if (unlikely((mapbits & CHUNK_MAP_ALLOCATED) == 0)) {
+		    __libc_fatal("Invalid address %p passed to free: value not allocated", ptr);
+		}
+#endif
 		if (likely((mapbits & CHUNK_MAP_LARGE) == 0)) {
 			/* Small allocation. */
 			if (likely(tcache != NULL)) {
diff --git a/include/jemalloc/internal/chunk.h b/include/jemalloc/internal/chunk.h
index 5d19383..df79de7 100644
--- a/include/jemalloc/internal/chunk.h
+++ b/include/jemalloc/internal/chunk.h
@@ -5,7 +5,11 @@
  * Size and alignment of memory chunks that are allocated by the OS's virtual
  * memory system.
  */
+#ifdef ANDROID_LG_CHUNK_DEFAULT
+#define	LG_CHUNK_DEFAULT	ANDROID_LG_CHUNK_DEFAULT
+#else
 #define	LG_CHUNK_DEFAULT	21
+#endif
 
 /* Return the chunk address for allocation address a. */
 #define	CHUNK_ADDR2BASE(a)						\
diff --git a/include/jemalloc/internal/jemalloc_internal.h b/include/jemalloc/internal/jemalloc_internal.h
index 8dbe0af..9f5cfa6 100644
--- a/include/jemalloc/internal/jemalloc_internal.h
+++ b/include/jemalloc/internal/jemalloc_internal.h
@@ -70,6 +70,13 @@
     false
 #endif
     ;
+static const bool maps_coalesce =
+#ifdef JEMALLOC_MAPS_COALESCE
+    true
+#else
+    false
+#endif
+    ;
 static const bool config_munmap =
 #ifdef JEMALLOC_MUNMAP
     true
@@ -177,7 +184,7 @@
 #include "jemalloc/internal/jemalloc_internal_macros.h"
 
 /* Size class index type. */
-typedef unsigned index_t;
+typedef unsigned szind_t;
 
 /*
  * Flags bits:
@@ -360,6 +367,7 @@
 #include "jemalloc/internal/bitmap.h"
 #include "jemalloc/internal/base.h"
 #include "jemalloc/internal/rtree.h"
+#include "jemalloc/internal/pages.h"
 #include "jemalloc/internal/chunk.h"
 #include "jemalloc/internal/huge.h"
 #include "jemalloc/internal/tcache.h"
@@ -391,6 +399,7 @@
 #undef JEMALLOC_ARENA_STRUCTS_B
 #include "jemalloc/internal/base.h"
 #include "jemalloc/internal/rtree.h"
+#include "jemalloc/internal/pages.h"
 #include "jemalloc/internal/chunk.h"
 #include "jemalloc/internal/huge.h"
 #include "jemalloc/internal/tcache.h"
@@ -470,6 +479,7 @@
 #include "jemalloc/internal/arena.h"
 #include "jemalloc/internal/base.h"
 #include "jemalloc/internal/rtree.h"
+#include "jemalloc/internal/pages.h"
 #include "jemalloc/internal/chunk.h"
 #include "jemalloc/internal/huge.h"
 #include "jemalloc/internal/tcache.h"
@@ -496,16 +506,17 @@
 #include "jemalloc/internal/extent.h"
 #include "jemalloc/internal/base.h"
 #include "jemalloc/internal/rtree.h"
+#include "jemalloc/internal/pages.h"
 #include "jemalloc/internal/chunk.h"
 #include "jemalloc/internal/huge.h"
 
 #ifndef JEMALLOC_ENABLE_INLINE
-index_t	size2index_compute(size_t size);
-index_t	size2index_lookup(size_t size);
-index_t	size2index(size_t size);
-size_t	index2size_compute(index_t index);
-size_t	index2size_lookup(index_t index);
-size_t	index2size(index_t index);
+szind_t	size2index_compute(size_t size);
+szind_t	size2index_lookup(size_t size);
+szind_t	size2index(size_t size);
+size_t	index2size_compute(szind_t index);
+size_t	index2size_lookup(szind_t index);
+size_t	index2size(szind_t index);
 size_t	s2u_compute(size_t size);
 size_t	s2u_lookup(size_t size);
 size_t	s2u(size_t size);
@@ -516,7 +527,7 @@
 #endif
 
 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
-JEMALLOC_INLINE index_t
+JEMALLOC_INLINE szind_t
 size2index_compute(size_t size)
 {
 
@@ -525,7 +536,7 @@
 		size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
 		size_t lg_ceil = lg_floor(pow2_ceil(size));
 		return (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin);
-	} else
+	}
 #endif
 	{
 		size_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
@@ -547,7 +558,7 @@
 	}
 }
 
-JEMALLOC_ALWAYS_INLINE index_t
+JEMALLOC_ALWAYS_INLINE szind_t
 size2index_lookup(size_t size)
 {
 
@@ -560,25 +571,23 @@
 	}
 }
 
-JEMALLOC_ALWAYS_INLINE index_t
+JEMALLOC_ALWAYS_INLINE szind_t
 size2index(size_t size)
 {
 
 	assert(size > 0);
 	if (likely(size <= LOOKUP_MAXCLASS))
 		return (size2index_lookup(size));
-	else
-		return (size2index_compute(size));
+	return (size2index_compute(size));
 }
 
 JEMALLOC_INLINE size_t
-index2size_compute(index_t index)
+index2size_compute(szind_t index)
 {
 
 #if (NTBINS > 0)
 	if (index < NTBINS)
 		return (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index));
-	else
 #endif
 	{
 		size_t reduced_index = index - NTBINS;
@@ -600,7 +609,7 @@
 }
 
 JEMALLOC_ALWAYS_INLINE size_t
-index2size_lookup(index_t index)
+index2size_lookup(szind_t index)
 {
 	size_t ret = (size_t)index2size_tab[index];
 	assert(ret == index2size_compute(index));
@@ -608,7 +617,7 @@
 }
 
 JEMALLOC_ALWAYS_INLINE size_t
-index2size(index_t index)
+index2size(szind_t index)
 {
 
 	assert(index < NSIZES);
@@ -625,7 +634,7 @@
 		size_t lg_ceil = lg_floor(pow2_ceil(size));
 		return (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) :
 		    (ZU(1) << lg_ceil));
-	} else
+	}
 #endif
 	{
 		size_t x = unlikely(ZI(size) < 0) ? ((size<<1) ?
@@ -660,8 +669,7 @@
 	assert(size > 0);
 	if (likely(size <= LOOKUP_MAXCLASS))
 		return (s2u_lookup(size));
-	else
-		return (s2u_compute(size));
+	return (s2u_compute(size));
 }
 
 /*
@@ -711,7 +719,7 @@
 		 * Calculate the size of the over-size run that arena_palloc()
 		 * would need to allocate in order to guarantee the alignment.
 		 */
-		if (usize + alignment - PAGE <= arena_maxrun)
+		if (usize + large_pad + alignment - PAGE <= arena_maxrun)
 			return (usize);
 	}
 
@@ -968,7 +976,7 @@
 	size_t ret;
 
 	if (usize <= SMALL_MAXCLASS) {
-		index_t binind = size2index(usize);
+		szind_t binind = size2index(usize);
 		ret = arena_bin_info[binind].redzone_size;
 	} else
 		ret = 0;
diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h b/include/jemalloc/internal/jemalloc_internal_defs.h
index ab589f3..1c4b8a6 100644
--- a/include/jemalloc/internal/jemalloc_internal_defs.h
+++ b/include/jemalloc/internal/jemalloc_internal_defs.h
@@ -28,7 +28,7 @@
 #endif
 
 /* Defined if C11 atomics are available. */
-#define JEMALLOC_C11ATOMICS
+#define JEMALLOC_C11ATOMICS 
 
 /* Defined if the equivalent of FreeBSD's atomic(9) functions are available. */
 /* #undef JEMALLOC_ATOMIC9 */
@@ -175,6 +175,15 @@
 #define LG_PAGE 12
 
 /*
+ * If defined, adjacent virtual memory mappings with identical attributes
+ * automatically coalesce, and they fragment when changes are made to subranges.
+ * This is the normal order of things for mmap()/munmap(), but on Windows
+ * VirtualAlloc()/VirtualFree() operations must be precisely matched, i.e.
+ * mappings do *not* coalesce/fragment.
+ */
+#define JEMALLOC_MAPS_COALESCE 
+
+/*
  * If defined, use munmap() to unmap freed chunks, rather than storing them for
  * later reuse.  This is disabled by default on Linux because common sequences
  * of mmap()/munmap() calls will cause virtual memory map holes.
@@ -201,7 +210,7 @@
  * If defined, explicitly attempt to more uniformly distribute large allocation
  * pointer alignments across all cache indices.
  */
-/* #undef JEMALLOC_CACHE_OBLIVIOUS */
+#define JEMALLOC_CACHE_OBLIVIOUS 
 
 /*
  * Darwin (OS X) uses zones to work around Mach-O symbol override shortcomings.
diff --git a/include/jemalloc/internal/private_namespace.h b/include/jemalloc/internal/private_namespace.h
index 594089f..da2062a 100644
--- a/include/jemalloc/internal/private_namespace.h
+++ b/include/jemalloc/internal/private_namespace.h
@@ -2,8 +2,6 @@
 #define	a0get JEMALLOC_N(a0get)
 #define	a0malloc JEMALLOC_N(a0malloc)
 #define	arena_aalloc JEMALLOC_N(arena_aalloc)
-#define	arena_get JEMALLOC_N(arena_get)
-#define	arena_get_hard JEMALLOC_N(arena_get_hard)
 #define	arena_alloc_junk_small JEMALLOC_N(arena_alloc_junk_small)
 #define	arena_bin_index JEMALLOC_N(arena_bin_index)
 #define	arena_bin_info JEMALLOC_N(arena_bin_info)
@@ -29,6 +27,8 @@
 #define	arena_dalloc_small JEMALLOC_N(arena_dalloc_small)
 #define	arena_dss_prec_get JEMALLOC_N(arena_dss_prec_get)
 #define	arena_dss_prec_set JEMALLOC_N(arena_dss_prec_set)
+#define	arena_get JEMALLOC_N(arena_get)
+#define	arena_get_hard JEMALLOC_N(arena_get_hard)
 #define	arena_init JEMALLOC_N(arena_init)
 #define	arena_lg_dirty_mult_default_get JEMALLOC_N(arena_lg_dirty_mult_default_get)
 #define	arena_lg_dirty_mult_default_set JEMALLOC_N(arena_lg_dirty_mult_default_set)
@@ -39,22 +39,25 @@
 #define	arena_malloc_small JEMALLOC_N(arena_malloc_small)
 #define	arena_mapbits_allocated_get JEMALLOC_N(arena_mapbits_allocated_get)
 #define	arena_mapbits_binind_get JEMALLOC_N(arena_mapbits_binind_get)
+#define	arena_mapbits_decommitted_get JEMALLOC_N(arena_mapbits_decommitted_get)
 #define	arena_mapbits_dirty_get JEMALLOC_N(arena_mapbits_dirty_get)
 #define	arena_mapbits_get JEMALLOC_N(arena_mapbits_get)
+#define	arena_mapbits_internal_set JEMALLOC_N(arena_mapbits_internal_set)
 #define	arena_mapbits_large_binind_set JEMALLOC_N(arena_mapbits_large_binind_set)
 #define	arena_mapbits_large_get JEMALLOC_N(arena_mapbits_large_get)
 #define	arena_mapbits_large_set JEMALLOC_N(arena_mapbits_large_set)
 #define	arena_mapbits_large_size_get JEMALLOC_N(arena_mapbits_large_size_get)
+#define	arena_mapbitsp_get JEMALLOC_N(arena_mapbitsp_get)
+#define	arena_mapbitsp_read JEMALLOC_N(arena_mapbitsp_read)
+#define	arena_mapbitsp_write JEMALLOC_N(arena_mapbitsp_write)
+#define	arena_mapbits_size_decode JEMALLOC_N(arena_mapbits_size_decode)
+#define	arena_mapbits_size_encode JEMALLOC_N(arena_mapbits_size_encode)
 #define	arena_mapbits_small_runind_get JEMALLOC_N(arena_mapbits_small_runind_get)
 #define	arena_mapbits_small_set JEMALLOC_N(arena_mapbits_small_set)
 #define	arena_mapbits_unallocated_set JEMALLOC_N(arena_mapbits_unallocated_set)
 #define	arena_mapbits_unallocated_size_get JEMALLOC_N(arena_mapbits_unallocated_size_get)
 #define	arena_mapbits_unallocated_size_set JEMALLOC_N(arena_mapbits_unallocated_size_set)
 #define	arena_mapbits_unzeroed_get JEMALLOC_N(arena_mapbits_unzeroed_get)
-#define	arena_mapbits_unzeroed_set JEMALLOC_N(arena_mapbits_unzeroed_set)
-#define	arena_mapbitsp_get JEMALLOC_N(arena_mapbitsp_get)
-#define	arena_mapbitsp_read JEMALLOC_N(arena_mapbitsp_read)
-#define	arena_mapbitsp_write JEMALLOC_N(arena_mapbitsp_write)
 #define	arena_maxclass JEMALLOC_N(arena_maxclass)
 #define	arena_maxrun JEMALLOC_N(arena_maxrun)
 #define	arena_maybe_purge JEMALLOC_N(arena_maybe_purge)
@@ -90,11 +93,11 @@
 #define	arena_run_regind JEMALLOC_N(arena_run_regind)
 #define	arena_run_to_miscelm JEMALLOC_N(arena_run_to_miscelm)
 #define	arena_salloc JEMALLOC_N(arena_salloc)
+#define	arenas_cache_bypass_cleanup JEMALLOC_N(arenas_cache_bypass_cleanup)
+#define	arenas_cache_cleanup JEMALLOC_N(arenas_cache_cleanup)
 #define	arena_sdalloc JEMALLOC_N(arena_sdalloc)
 #define	arena_stats_merge JEMALLOC_N(arena_stats_merge)
 #define	arena_tcache_fill_small JEMALLOC_N(arena_tcache_fill_small)
-#define	arenas_cache_bypass_cleanup JEMALLOC_N(arenas_cache_bypass_cleanup)
-#define	arenas_cache_cleanup JEMALLOC_N(arenas_cache_cleanup)
 #define	atomic_add_p JEMALLOC_N(atomic_add_p)
 #define	atomic_add_u JEMALLOC_N(atomic_add_u)
 #define	atomic_add_uint32 JEMALLOC_N(atomic_add_uint32)
@@ -130,16 +133,14 @@
 #define	bootstrap_malloc JEMALLOC_N(bootstrap_malloc)
 #define	bt_init JEMALLOC_N(bt_init)
 #define	buferror JEMALLOC_N(buferror)
-#define	chunk_alloc_cache JEMALLOC_N(chunk_alloc_cache)
 #define	chunk_alloc_base JEMALLOC_N(chunk_alloc_base)
-#define	chunk_alloc_default JEMALLOC_N(chunk_alloc_default)
+#define	chunk_alloc_cache JEMALLOC_N(chunk_alloc_cache)
 #define	chunk_alloc_dss JEMALLOC_N(chunk_alloc_dss)
 #define	chunk_alloc_mmap JEMALLOC_N(chunk_alloc_mmap)
 #define	chunk_alloc_wrapper JEMALLOC_N(chunk_alloc_wrapper)
 #define	chunk_boot JEMALLOC_N(chunk_boot)
 #define	chunk_dalloc_arena JEMALLOC_N(chunk_dalloc_arena)
 #define	chunk_dalloc_cache JEMALLOC_N(chunk_dalloc_cache)
-#define	chunk_dalloc_default JEMALLOC_N(chunk_dalloc_default)
 #define	chunk_dalloc_mmap JEMALLOC_N(chunk_dalloc_mmap)
 #define	chunk_dalloc_wrapper JEMALLOC_N(chunk_dalloc_wrapper)
 #define	chunk_deregister JEMALLOC_N(chunk_deregister)
@@ -149,6 +150,9 @@
 #define	chunk_dss_prec_get JEMALLOC_N(chunk_dss_prec_get)
 #define	chunk_dss_prec_set JEMALLOC_N(chunk_dss_prec_set)
 #define	chunk_dss_prefork JEMALLOC_N(chunk_dss_prefork)
+#define	chunk_hooks_default JEMALLOC_N(chunk_hooks_default)
+#define	chunk_hooks_get JEMALLOC_N(chunk_hooks_get)
+#define	chunk_hooks_set JEMALLOC_N(chunk_hooks_set)
 #define	chunk_in_dss JEMALLOC_N(chunk_in_dss)
 #define	chunk_lookup JEMALLOC_N(chunk_lookup)
 #define	chunk_npages JEMALLOC_N(chunk_npages)
@@ -156,30 +160,22 @@
 #define	chunk_postfork_parent JEMALLOC_N(chunk_postfork_parent)
 #define	chunk_prefork JEMALLOC_N(chunk_prefork)
 #define	chunk_purge_arena JEMALLOC_N(chunk_purge_arena)
-#define	chunk_purge_default JEMALLOC_N(chunk_purge_default)
 #define	chunk_purge_wrapper JEMALLOC_N(chunk_purge_wrapper)
-#define	chunk_record JEMALLOC_N(chunk_record)
 #define	chunk_register JEMALLOC_N(chunk_register)
-#define	chunks_rtree JEMALLOC_N(chunks_rtree)
 #define	chunksize JEMALLOC_N(chunksize)
 #define	chunksize_mask JEMALLOC_N(chunksize_mask)
-#define	ckh_bucket_search JEMALLOC_N(ckh_bucket_search)
+#define	chunks_rtree JEMALLOC_N(chunks_rtree)
 #define	ckh_count JEMALLOC_N(ckh_count)
 #define	ckh_delete JEMALLOC_N(ckh_delete)
-#define	ckh_evict_reloc_insert JEMALLOC_N(ckh_evict_reloc_insert)
 #define	ckh_insert JEMALLOC_N(ckh_insert)
-#define	ckh_isearch JEMALLOC_N(ckh_isearch)
 #define	ckh_iter JEMALLOC_N(ckh_iter)
 #define	ckh_new JEMALLOC_N(ckh_new)
 #define	ckh_pointer_hash JEMALLOC_N(ckh_pointer_hash)
 #define	ckh_pointer_keycomp JEMALLOC_N(ckh_pointer_keycomp)
-#define	ckh_rebuild JEMALLOC_N(ckh_rebuild)
 #define	ckh_remove JEMALLOC_N(ckh_remove)
 #define	ckh_search JEMALLOC_N(ckh_search)
 #define	ckh_string_hash JEMALLOC_N(ckh_string_hash)
 #define	ckh_string_keycomp JEMALLOC_N(ckh_string_keycomp)
-#define	ckh_try_bucket_insert JEMALLOC_N(ckh_try_bucket_insert)
-#define	ckh_try_insert JEMALLOC_N(ckh_try_insert)
 #define	ctl_boot JEMALLOC_N(ctl_boot)
 #define	ctl_bymib JEMALLOC_N(ctl_bymib)
 #define	ctl_byname JEMALLOC_N(ctl_byname)
@@ -250,12 +246,9 @@
 #define	hash_x86_128 JEMALLOC_N(hash_x86_128)
 #define	hash_x86_32 JEMALLOC_N(hash_x86_32)
 #define	huge_aalloc JEMALLOC_N(huge_aalloc)
-#define	huge_allocated JEMALLOC_N(huge_allocated)
 #define	huge_dalloc JEMALLOC_N(huge_dalloc)
 #define	huge_dalloc_junk JEMALLOC_N(huge_dalloc_junk)
 #define	huge_malloc JEMALLOC_N(huge_malloc)
-#define	huge_ndalloc JEMALLOC_N(huge_ndalloc)
-#define	huge_nmalloc JEMALLOC_N(huge_nmalloc)
 #define	huge_palloc JEMALLOC_N(huge_palloc)
 #define	huge_prof_tctx_get JEMALLOC_N(huge_prof_tctx_get)
 #define	huge_prof_tctx_set JEMALLOC_N(huge_prof_tctx_set)
@@ -271,11 +264,11 @@
 #define	idalloctm JEMALLOC_N(idalloctm)
 #define	imalloc JEMALLOC_N(imalloc)
 #define	imalloct JEMALLOC_N(imalloct)
-#define	in_valgrind JEMALLOC_N(in_valgrind)
 #define	index2size JEMALLOC_N(index2size)
 #define	index2size_compute JEMALLOC_N(index2size_compute)
 #define	index2size_lookup JEMALLOC_N(index2size_lookup)
 #define	index2size_tab JEMALLOC_N(index2size_tab)
+#define	in_valgrind JEMALLOC_N(in_valgrind)
 #define	ipalloc JEMALLOC_N(ipalloc)
 #define	ipalloct JEMALLOC_N(ipalloct)
 #define	ipallocztm JEMALLOC_N(ipallocztm)
@@ -285,8 +278,8 @@
 #define	iralloct_realign JEMALLOC_N(iralloct_realign)
 #define	isalloc JEMALLOC_N(isalloc)
 #define	isdalloct JEMALLOC_N(isdalloct)
-#define	isthreaded JEMALLOC_N(isthreaded)
 #define	isqalloc JEMALLOC_N(isqalloc)
+#define	isthreaded JEMALLOC_N(isthreaded)
 #define	ivsalloc JEMALLOC_N(ivsalloc)
 #define	ixalloc JEMALLOC_N(ixalloc)
 #define	jemalloc_postfork_child JEMALLOC_N(jemalloc_postfork_child)
@@ -347,7 +340,12 @@
 #define	opt_xmalloc JEMALLOC_N(opt_xmalloc)
 #define	opt_zero JEMALLOC_N(opt_zero)
 #define	p2rz JEMALLOC_N(p2rz)
+#define	pages_commit JEMALLOC_N(pages_commit)
+#define	pages_decommit JEMALLOC_N(pages_decommit)
+#define	pages_map JEMALLOC_N(pages_map)
 #define	pages_purge JEMALLOC_N(pages_purge)
+#define	pages_trim JEMALLOC_N(pages_trim)
+#define	pages_unmap JEMALLOC_N(pages_unmap)
 #define	pow2_ceil JEMALLOC_N(pow2_ceil)
 #define	prof_active_get JEMALLOC_N(prof_active_get)
 #define	prof_active_get_unlocked JEMALLOC_N(prof_active_get_unlocked)
@@ -358,7 +356,6 @@
 #define	prof_boot0 JEMALLOC_N(prof_boot0)
 #define	prof_boot1 JEMALLOC_N(prof_boot1)
 #define	prof_boot2 JEMALLOC_N(prof_boot2)
-#define	prof_bt_count JEMALLOC_N(prof_bt_count)
 #define	prof_dump_header JEMALLOC_N(prof_dump_header)
 #define	prof_dump_open JEMALLOC_N(prof_dump_open)
 #define	prof_free JEMALLOC_N(prof_free)
@@ -426,7 +423,6 @@
 #define	stats_cactive_add JEMALLOC_N(stats_cactive_add)
 #define	stats_cactive_get JEMALLOC_N(stats_cactive_get)
 #define	stats_cactive_sub JEMALLOC_N(stats_cactive_sub)
-#define	stats_chunks JEMALLOC_N(stats_chunks)
 #define	stats_print JEMALLOC_N(stats_print)
 #define	tcache_alloc_easy JEMALLOC_N(tcache_alloc_easy)
 #define	tcache_alloc_large JEMALLOC_N(tcache_alloc_large)
@@ -452,21 +448,21 @@
 #define	tcache_get JEMALLOC_N(tcache_get)
 #define	tcache_get_hard JEMALLOC_N(tcache_get_hard)
 #define	tcache_maxclass JEMALLOC_N(tcache_maxclass)
-#define	tcache_salloc JEMALLOC_N(tcache_salloc)
-#define	tcache_stats_merge JEMALLOC_N(tcache_stats_merge)
 #define	tcaches JEMALLOC_N(tcaches)
+#define	tcache_salloc JEMALLOC_N(tcache_salloc)
 #define	tcaches_create JEMALLOC_N(tcaches_create)
 #define	tcaches_destroy JEMALLOC_N(tcaches_destroy)
 #define	tcaches_flush JEMALLOC_N(tcaches_flush)
 #define	tcaches_get JEMALLOC_N(tcaches_get)
+#define	tcache_stats_merge JEMALLOC_N(tcache_stats_merge)
 #define	thread_allocated_cleanup JEMALLOC_N(thread_allocated_cleanup)
 #define	thread_deallocated_cleanup JEMALLOC_N(thread_deallocated_cleanup)
-#define	tsd_booted JEMALLOC_N(tsd_booted)
 #define	tsd_arena_get JEMALLOC_N(tsd_arena_get)
 #define	tsd_arena_set JEMALLOC_N(tsd_arena_set)
 #define	tsd_boot JEMALLOC_N(tsd_boot)
 #define	tsd_boot0 JEMALLOC_N(tsd_boot0)
 #define	tsd_boot1 JEMALLOC_N(tsd_boot1)
+#define	tsd_booted JEMALLOC_N(tsd_booted)
 #define	tsd_cleanup JEMALLOC_N(tsd_cleanup)
 #define	tsd_cleanup_wrapper JEMALLOC_N(tsd_cleanup_wrapper)
 #define	tsd_fetch JEMALLOC_N(tsd_fetch)
diff --git a/include/jemalloc/internal/private_unnamespace.h b/include/jemalloc/internal/private_unnamespace.h
index 50475fd..15b0230 100644
--- a/include/jemalloc/internal/private_unnamespace.h
+++ b/include/jemalloc/internal/private_unnamespace.h
@@ -2,8 +2,6 @@
 #undef a0get
 #undef a0malloc
 #undef arena_aalloc
-#undef arena_get
-#undef arena_get_hard
 #undef arena_alloc_junk_small
 #undef arena_bin_index
 #undef arena_bin_info
@@ -29,6 +27,8 @@
 #undef arena_dalloc_small
 #undef arena_dss_prec_get
 #undef arena_dss_prec_set
+#undef arena_get
+#undef arena_get_hard
 #undef arena_init
 #undef arena_lg_dirty_mult_default_get
 #undef arena_lg_dirty_mult_default_set
@@ -39,22 +39,25 @@
 #undef arena_malloc_small
 #undef arena_mapbits_allocated_get
 #undef arena_mapbits_binind_get
+#undef arena_mapbits_decommitted_get
 #undef arena_mapbits_dirty_get
 #undef arena_mapbits_get
+#undef arena_mapbits_internal_set
 #undef arena_mapbits_large_binind_set
 #undef arena_mapbits_large_get
 #undef arena_mapbits_large_set
 #undef arena_mapbits_large_size_get
+#undef arena_mapbitsp_get
+#undef arena_mapbitsp_read
+#undef arena_mapbitsp_write
+#undef arena_mapbits_size_decode
+#undef arena_mapbits_size_encode
 #undef arena_mapbits_small_runind_get
 #undef arena_mapbits_small_set
 #undef arena_mapbits_unallocated_set
 #undef arena_mapbits_unallocated_size_get
 #undef arena_mapbits_unallocated_size_set
 #undef arena_mapbits_unzeroed_get
-#undef arena_mapbits_unzeroed_set
-#undef arena_mapbitsp_get
-#undef arena_mapbitsp_read
-#undef arena_mapbitsp_write
 #undef arena_maxclass
 #undef arena_maxrun
 #undef arena_maybe_purge
@@ -90,11 +93,11 @@
 #undef arena_run_regind
 #undef arena_run_to_miscelm
 #undef arena_salloc
+#undef arenas_cache_bypass_cleanup
+#undef arenas_cache_cleanup
 #undef arena_sdalloc
 #undef arena_stats_merge
 #undef arena_tcache_fill_small
-#undef arenas_cache_bypass_cleanup
-#undef arenas_cache_cleanup
 #undef atomic_add_p
 #undef atomic_add_u
 #undef atomic_add_uint32
@@ -130,16 +133,14 @@
 #undef bootstrap_malloc
 #undef bt_init
 #undef buferror
-#undef chunk_alloc_cache
 #undef chunk_alloc_base
-#undef chunk_alloc_default
+#undef chunk_alloc_cache
 #undef chunk_alloc_dss
 #undef chunk_alloc_mmap
 #undef chunk_alloc_wrapper
 #undef chunk_boot
 #undef chunk_dalloc_arena
 #undef chunk_dalloc_cache
-#undef chunk_dalloc_default
 #undef chunk_dalloc_mmap
 #undef chunk_dalloc_wrapper
 #undef chunk_deregister
@@ -149,6 +150,9 @@
 #undef chunk_dss_prec_get
 #undef chunk_dss_prec_set
 #undef chunk_dss_prefork
+#undef chunk_hooks_default
+#undef chunk_hooks_get
+#undef chunk_hooks_set
 #undef chunk_in_dss
 #undef chunk_lookup
 #undef chunk_npages
@@ -156,30 +160,22 @@
 #undef chunk_postfork_parent
 #undef chunk_prefork
 #undef chunk_purge_arena
-#undef chunk_purge_default
 #undef chunk_purge_wrapper
-#undef chunk_record
 #undef chunk_register
-#undef chunks_rtree
 #undef chunksize
 #undef chunksize_mask
-#undef ckh_bucket_search
+#undef chunks_rtree
 #undef ckh_count
 #undef ckh_delete
-#undef ckh_evict_reloc_insert
 #undef ckh_insert
-#undef ckh_isearch
 #undef ckh_iter
 #undef ckh_new
 #undef ckh_pointer_hash
 #undef ckh_pointer_keycomp
-#undef ckh_rebuild
 #undef ckh_remove
 #undef ckh_search
 #undef ckh_string_hash
 #undef ckh_string_keycomp
-#undef ckh_try_bucket_insert
-#undef ckh_try_insert
 #undef ctl_boot
 #undef ctl_bymib
 #undef ctl_byname
@@ -250,12 +246,9 @@
 #undef hash_x86_128
 #undef hash_x86_32
 #undef huge_aalloc
-#undef huge_allocated
 #undef huge_dalloc
 #undef huge_dalloc_junk
 #undef huge_malloc
-#undef huge_ndalloc
-#undef huge_nmalloc
 #undef huge_palloc
 #undef huge_prof_tctx_get
 #undef huge_prof_tctx_set
@@ -271,11 +264,11 @@
 #undef idalloctm
 #undef imalloc
 #undef imalloct
-#undef in_valgrind
 #undef index2size
 #undef index2size_compute
 #undef index2size_lookup
 #undef index2size_tab
+#undef in_valgrind
 #undef ipalloc
 #undef ipalloct
 #undef ipallocztm
@@ -285,8 +278,8 @@
 #undef iralloct_realign
 #undef isalloc
 #undef isdalloct
-#undef isthreaded
 #undef isqalloc
+#undef isthreaded
 #undef ivsalloc
 #undef ixalloc
 #undef jemalloc_postfork_child
@@ -347,7 +340,12 @@
 #undef opt_xmalloc
 #undef opt_zero
 #undef p2rz
+#undef pages_commit
+#undef pages_decommit
+#undef pages_map
 #undef pages_purge
+#undef pages_trim
+#undef pages_unmap
 #undef pow2_ceil
 #undef prof_active_get
 #undef prof_active_get_unlocked
@@ -358,7 +356,6 @@
 #undef prof_boot0
 #undef prof_boot1
 #undef prof_boot2
-#undef prof_bt_count
 #undef prof_dump_header
 #undef prof_dump_open
 #undef prof_free
@@ -426,7 +423,6 @@
 #undef stats_cactive_add
 #undef stats_cactive_get
 #undef stats_cactive_sub
-#undef stats_chunks
 #undef stats_print
 #undef tcache_alloc_easy
 #undef tcache_alloc_large
@@ -452,21 +448,21 @@
 #undef tcache_get
 #undef tcache_get_hard
 #undef tcache_maxclass
-#undef tcache_salloc
-#undef tcache_stats_merge
 #undef tcaches
+#undef tcache_salloc
 #undef tcaches_create
 #undef tcaches_destroy
 #undef tcaches_flush
 #undef tcaches_get
+#undef tcache_stats_merge
 #undef thread_allocated_cleanup
 #undef thread_deallocated_cleanup
-#undef tsd_booted
 #undef tsd_arena_get
 #undef tsd_arena_set
 #undef tsd_boot
 #undef tsd_boot0
 #undef tsd_boot1
+#undef tsd_booted
 #undef tsd_cleanup
 #undef tsd_cleanup_wrapper
 #undef tsd_fetch
diff --git a/include/jemalloc/internal/size_classes.h b/include/jemalloc/internal/size_classes.h
index 6cf477e..a33d50b 100644
--- a/include/jemalloc/internal/size_classes.h
+++ b/include/jemalloc/internal/size_classes.h
@@ -8,7 +8,8 @@
  *
  *   LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling.
  *   SIZE_CLASSES: Complete table of
- *                 SC(index, lg_delta, size, bin, lg_delta_lookup) tuples.
+ *                 SC(index, lg_grp, lg_delta, ndelta, bin, lg_delta_lookup)
+ *                 tuples.
  *     index: Size class index.
  *     lg_grp: Lg group base size (no deltas added).
  *     lg_delta: Lg delta to previous size class.
diff --git a/include/jemalloc/jemalloc.h b/include/jemalloc/jemalloc.h
index 228db77..efdb866 100644
--- a/include/jemalloc/jemalloc.h
+++ b/include/jemalloc/jemalloc.h
@@ -7,13 +7,22 @@
 /* Defined if __attribute__((...)) syntax is supported. */
 #define	JEMALLOC_HAVE_ATTR
 
+/* Defined if alloc_size attribute is supported. */
+#define	JEMALLOC_HAVE_ATTR_ALLOC_SIZE
+
+/* Defined if format(gnu_printf, ...) attribute is supported. */
+#define	JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF
+
+/* Defined if format(printf, ...) attribute is supported. */
+#define	JEMALLOC_HAVE_ATTR_FORMAT_PRINTF
+
 /*
  * Define overrides for non-standard allocator-related functions if they are
  * present on the system.
  */
 #define	JEMALLOC_OVERRIDE_MEMALIGN
-#if !defined(__LP64__)
-#define	JEMALLOC_OVERRIDE_VALLOC
+#ifndef __LP64__
+#define JEMALLOC_OVERRIDE_VALLOC
 #endif
 
 /*
@@ -25,6 +34,13 @@
  */
 #define	JEMALLOC_USABLE_SIZE_CONST const
 
+/*
+ * If defined, specify throw() for the public function prototypes when compiling
+ * with C++.  The only justification for this is to match the prototypes that
+ * glibc defines.
+ */
+/* #undef	JEMALLOC_USE_CXX_THROW */
+
 /* sizeof(void *) == 2^LG_SIZEOF_PTR. */
 #ifdef __LP64__
 #define	LG_SIZEOF_PTR 3
@@ -68,12 +84,12 @@
 #include <limits.h>
 #include <strings.h>
 
-#define	JEMALLOC_VERSION "3.6.0-129-g3cae39166d1fc58873c5df3c0c96b45d49cb5778"
-#define	JEMALLOC_VERSION_MAJOR 3
-#define	JEMALLOC_VERSION_MINOR 6
+#define	JEMALLOC_VERSION "4.0.0-165-g3d03eb8b8d0b2cd8f3f7ef39ec62ed9e42e2d3e3"
+#define	JEMALLOC_VERSION_MAJOR 4
+#define	JEMALLOC_VERSION_MINOR 0
 #define	JEMALLOC_VERSION_BUGFIX 0
-#define	JEMALLOC_VERSION_NREV 129
-#define	JEMALLOC_VERSION_GID "3cae39166d1fc58873c5df3c0c96b45d49cb5778"
+#define	JEMALLOC_VERSION_NREV 165
+#define	JEMALLOC_VERSION_GID "3d03eb8b8d0b2cd8f3f7ef39ec62ed9e42e2d3e3"
 
 #  define MALLOCX_LG_ALIGN(la)	(la)
 #  if LG_SIZEOF_PTR == 2
@@ -94,16 +110,42 @@
  */
 #  define MALLOCX_ARENA(a)	((int)(((a)+1) << 20))
 
+#if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW)
+#  define JEMALLOC_CXX_THROW throw()
+#else
+#  define JEMALLOC_CXX_THROW
+#endif
+
 #ifdef JEMALLOC_HAVE_ATTR
 #  define JEMALLOC_ATTR(s) __attribute__((s))
+#  define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
+#  ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE
+#    define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s))
+#    define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2))
+#  else
+#    define JEMALLOC_ALLOC_SIZE(s)
+#    define JEMALLOC_ALLOC_SIZE2(s1, s2)
+#  endif
 #  ifndef JEMALLOC_EXPORT
 #    define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default"))
 #  endif
-#  define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
-#  define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
+#  ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF
+#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i))
+#  elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF)
+#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i))
+#  else
+#    define JEMALLOC_FORMAT_PRINTF(s, i)
+#  endif
 #  define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)
+#  define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow)
+#  define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
+#  define JEMALLOC_RESTRICT_RETURN
+#  define JEMALLOC_ALLOCATOR
 #elif _MSC_VER
 #  define JEMALLOC_ATTR(s)
+#  define JEMALLOC_ALIGNED(s) __declspec(align(s))
+#  define JEMALLOC_ALLOC_SIZE(s)
+#  define JEMALLOC_ALLOC_SIZE2(s1, s2)
 #  ifndef JEMALLOC_EXPORT
 #    ifdef DLLEXPORT
 #      define JEMALLOC_EXPORT __declspec(dllexport)
@@ -111,15 +153,32 @@
 #      define JEMALLOC_EXPORT __declspec(dllimport)
 #    endif
 #  endif
-#  define JEMALLOC_ALIGNED(s) __declspec(align(s))
-#  define JEMALLOC_SECTION(s) __declspec(allocate(s))
+#  define JEMALLOC_FORMAT_PRINTF(s, i)
 #  define JEMALLOC_NOINLINE __declspec(noinline)
+#  ifdef __cplusplus
+#    define JEMALLOC_NOTHROW __declspec(nothrow)
+#  else
+#    define JEMALLOC_NOTHROW
+#  endif
+#  define JEMALLOC_SECTION(s) __declspec(allocate(s))
+#  define JEMALLOC_RESTRICT_RETURN __declspec(restrict)
+#  if _MSC_VER >= 1900 && !defined(__EDG__)
+#    define JEMALLOC_ALLOCATOR __declspec(allocator)
+#  else
+#    define JEMALLOC_ALLOCATOR
+#  endif
 #else
 #  define JEMALLOC_ATTR(s)
-#  define JEMALLOC_EXPORT
 #  define JEMALLOC_ALIGNED(s)
-#  define JEMALLOC_SECTION(s)
+#  define JEMALLOC_ALLOC_SIZE(s)
+#  define JEMALLOC_ALLOC_SIZE2(s1, s2)
+#  define JEMALLOC_EXPORT
+#  define JEMALLOC_FORMAT_PRINTF(s, i)
 #  define JEMALLOC_NOINLINE
+#  define JEMALLOC_NOTHROW
+#  define JEMALLOC_SECTION(s)
+#  define JEMALLOC_RESTRICT_RETURN
+#  define JEMALLOC_ALLOCATOR
 #endif
 
 /*
@@ -131,51 +190,121 @@
 extern JEMALLOC_EXPORT void		(*je_malloc_message)(void *cbopaque,
     const char *s);
 
-JEMALLOC_EXPORT void	*je_malloc(size_t size) JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*je_calloc(size_t num, size_t size)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT int	je_posix_memalign(void **memptr, size_t alignment,
-    size_t size) JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT void	*je_aligned_alloc(size_t alignment, size_t size)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*je_realloc(void *ptr, size_t size);
-JEMALLOC_EXPORT void	je_free(void *ptr);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_malloc(size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_calloc(size_t num, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_posix_memalign(void **memptr,
+    size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1));
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_aligned_alloc(size_t alignment,
+    size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc)
+    JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_realloc(void *ptr, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_free(void *ptr)
+    JEMALLOC_CXX_THROW;
 
-JEMALLOC_EXPORT void	*je_mallocx(size_t size, int flags)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*je_rallocx(void *ptr, size_t size, int flags);
-JEMALLOC_EXPORT size_t	je_xallocx(void *ptr, size_t size, size_t extra,
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_mallocx(size_t size, int flags)
+    JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_rallocx(void *ptr, size_t size,
+    int flags) JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_xallocx(void *ptr, size_t size,
+    size_t extra, int flags);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_sallocx(const void *ptr,
+    int flags) JEMALLOC_ATTR(pure);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_dallocx(void *ptr, int flags);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_sdallocx(void *ptr, size_t size,
     int flags);
-JEMALLOC_EXPORT size_t	je_sallocx(const void *ptr, int flags)
-    JEMALLOC_ATTR(pure);
-JEMALLOC_EXPORT void	je_dallocx(void *ptr, int flags);
-JEMALLOC_EXPORT void	je_sdallocx(void *ptr, size_t size, int flags);
-JEMALLOC_EXPORT size_t	je_nallocx(size_t size, int flags)
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_nallocx(size_t size, int flags)
     JEMALLOC_ATTR(pure);
 
-JEMALLOC_EXPORT int	je_mallctl(const char *name, void *oldp,
-    size_t *oldlenp, void *newp, size_t newlen);
-JEMALLOC_EXPORT int	je_mallctlnametomib(const char *name, size_t *mibp,
-    size_t *miblenp);
-JEMALLOC_EXPORT int	je_mallctlbymib(const size_t *mib, size_t miblen,
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_mallctl(const char *name,
     void *oldp, size_t *oldlenp, void *newp, size_t newlen);
-JEMALLOC_EXPORT void	je_malloc_stats_print(void (*write_cb)(void *,
-    const char *), void *je_cbopaque, const char *opts);
-JEMALLOC_EXPORT size_t	je_malloc_usable_size(
-    JEMALLOC_USABLE_SIZE_CONST void *ptr);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_mallctlnametomib(const char *name,
+    size_t *mibp, size_t *miblenp);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_mallctlbymib(const size_t *mib,
+    size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_malloc_stats_print(
+    void (*write_cb)(void *, const char *), void *je_cbopaque,
+    const char *opts);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_malloc_usable_size(
+    JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW;
 
 #ifdef JEMALLOC_OVERRIDE_MEMALIGN
-JEMALLOC_EXPORT void *	je_memalign(size_t alignment, size_t size)
-    JEMALLOC_ATTR(malloc);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_memalign(size_t alignment, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc);
 #endif
 
 #ifdef JEMALLOC_OVERRIDE_VALLOC
-JEMALLOC_EXPORT void *	je_valloc(size_t size) JEMALLOC_ATTR(malloc);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_valloc(size_t size) JEMALLOC_CXX_THROW
+    JEMALLOC_ATTR(malloc);
 #endif
 
-typedef void *(chunk_alloc_t)(void *, size_t, size_t, bool *, unsigned);
-typedef bool (chunk_dalloc_t)(void *, size_t, unsigned);
-typedef bool (chunk_purge_t)(void *, size_t, size_t, unsigned);
+/*
+ * void *
+ * chunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero,
+ *     bool *commit, unsigned arena_ind);
+ */
+typedef void *(chunk_alloc_t)(void *, size_t, size_t, bool *, bool *, unsigned);
+
+/*
+ * bool
+ * chunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind);
+ */
+typedef bool (chunk_dalloc_t)(void *, size_t, bool, unsigned);
+
+/*
+ * bool
+ * chunk_commit(void *chunk, size_t size, size_t offset, size_t length,
+ *     unsigned arena_ind);
+ */
+typedef bool (chunk_commit_t)(void *, size_t, size_t, size_t, unsigned);
+
+/*
+ * bool
+ * chunk_decommit(void *chunk, size_t size, size_t offset, size_t length,
+ *     unsigned arena_ind);
+ */
+typedef bool (chunk_decommit_t)(void *, size_t, size_t, size_t, unsigned);
+
+/*
+ * bool
+ * chunk_purge(void *chunk, size_t size, size_t offset, size_t length,
+ *     unsigned arena_ind);
+ */
+typedef bool (chunk_purge_t)(void *, size_t, size_t, size_t, unsigned);
+
+/*
+ * bool
+ * chunk_split(void *chunk, size_t size, size_t size_a, size_t size_b,
+ *     bool committed, unsigned arena_ind);
+ */
+typedef bool (chunk_split_t)(void *, size_t, size_t, size_t, bool, unsigned);
+
+/*
+ * bool
+ * chunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,
+ *     bool committed, unsigned arena_ind);
+ */
+typedef bool (chunk_merge_t)(void *, size_t, void *, size_t, bool, unsigned);
+
+typedef struct {
+	chunk_alloc_t		*alloc;
+	chunk_dalloc_t		*dalloc;
+	chunk_commit_t		*commit;
+	chunk_decommit_t	*decommit;
+	chunk_purge_t		*purge;
+	chunk_split_t		*split;
+	chunk_merge_t		*merge;
+} chunk_hooks_t;
 
 /*
  * By default application code must explicitly refer to mangled symbol names,
@@ -245,6 +374,6 @@
 #endif
 
 #ifdef __cplusplus
-};
+}
 #endif
 #endif /* JEMALLOC_H_ */
diff --git a/include/jemalloc/jemalloc_defs.h b/include/jemalloc/jemalloc_defs.h
index 2be505a..422ef67 100644
--- a/include/jemalloc/jemalloc_defs.h
+++ b/include/jemalloc/jemalloc_defs.h
@@ -2,12 +2,23 @@
 /* Defined if __attribute__((...)) syntax is supported. */
 #define JEMALLOC_HAVE_ATTR 
 
+/* Defined if alloc_size attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_ALLOC_SIZE 
+
+/* Defined if format(gnu_printf, ...) attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF 
+
+/* Defined if format(printf, ...) attribute is supported. */
+#define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF 
+
 /*
  * Define overrides for non-standard allocator-related functions if they are
  * present on the system.
  */
 #define JEMALLOC_OVERRIDE_MEMALIGN 
+#ifndef __LP64__
 #define JEMALLOC_OVERRIDE_VALLOC 
+#endif
 
 /*
  * At least Linux omits the "const" in:
@@ -18,6 +29,13 @@
  */
 #define JEMALLOC_USABLE_SIZE_CONST const
 
+/*
+ * If defined, specify throw() for the public function prototypes when compiling
+ * with C++.  The only justification for this is to match the prototypes that
+ * glibc defines.
+ */
+/* #undef JEMALLOC_USE_CXX_THROW */
+
 /* sizeof(void *) == 2^LG_SIZEOF_PTR. */
 #ifdef __LP64__
 #define LG_SIZEOF_PTR 3
diff --git a/include/jemalloc/jemalloc_macros.h b/include/jemalloc/jemalloc_macros.h
index ceb9a2b..3573bee 100644
--- a/include/jemalloc/jemalloc_macros.h
+++ b/include/jemalloc/jemalloc_macros.h
@@ -4,12 +4,12 @@
 #include <limits.h>
 #include <strings.h>
 
-#define	JEMALLOC_VERSION "3.6.0-129-g3cae39166d1fc58873c5df3c0c96b45d49cb5778"
-#define	JEMALLOC_VERSION_MAJOR 3
-#define	JEMALLOC_VERSION_MINOR 6
+#define	JEMALLOC_VERSION "4.0.0-165-g3d03eb8b8d0b2cd8f3f7ef39ec62ed9e42e2d3e3"
+#define	JEMALLOC_VERSION_MAJOR 4
+#define	JEMALLOC_VERSION_MINOR 0
 #define	JEMALLOC_VERSION_BUGFIX 0
-#define	JEMALLOC_VERSION_NREV 129
-#define	JEMALLOC_VERSION_GID "3cae39166d1fc58873c5df3c0c96b45d49cb5778"
+#define	JEMALLOC_VERSION_NREV 165
+#define	JEMALLOC_VERSION_GID "3d03eb8b8d0b2cd8f3f7ef39ec62ed9e42e2d3e3"
 
 #  define MALLOCX_LG_ALIGN(la)	(la)
 #  if LG_SIZEOF_PTR == 2
@@ -30,16 +30,42 @@
  */
 #  define MALLOCX_ARENA(a)	((int)(((a)+1) << 20))
 
+#if defined(__cplusplus) && defined(JEMALLOC_USE_CXX_THROW)
+#  define JEMALLOC_CXX_THROW throw()
+#else
+#  define JEMALLOC_CXX_THROW
+#endif
+
 #ifdef JEMALLOC_HAVE_ATTR
 #  define JEMALLOC_ATTR(s) __attribute__((s))
+#  define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
+#  ifdef JEMALLOC_HAVE_ATTR_ALLOC_SIZE
+#    define JEMALLOC_ALLOC_SIZE(s) JEMALLOC_ATTR(alloc_size(s))
+#    define JEMALLOC_ALLOC_SIZE2(s1, s2) JEMALLOC_ATTR(alloc_size(s1, s2))
+#  else
+#    define JEMALLOC_ALLOC_SIZE(s)
+#    define JEMALLOC_ALLOC_SIZE2(s1, s2)
+#  endif
 #  ifndef JEMALLOC_EXPORT
 #    define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default"))
 #  endif
-#  define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
-#  define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
+#  ifdef JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF
+#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(gnu_printf, s, i))
+#  elif defined(JEMALLOC_HAVE_ATTR_FORMAT_PRINTF)
+#    define JEMALLOC_FORMAT_PRINTF(s, i) JEMALLOC_ATTR(format(printf, s, i))
+#  else
+#    define JEMALLOC_FORMAT_PRINTF(s, i)
+#  endif
 #  define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)
+#  define JEMALLOC_NOTHROW JEMALLOC_ATTR(nothrow)
+#  define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
+#  define JEMALLOC_RESTRICT_RETURN
+#  define JEMALLOC_ALLOCATOR
 #elif _MSC_VER
 #  define JEMALLOC_ATTR(s)
+#  define JEMALLOC_ALIGNED(s) __declspec(align(s))
+#  define JEMALLOC_ALLOC_SIZE(s)
+#  define JEMALLOC_ALLOC_SIZE2(s1, s2)
 #  ifndef JEMALLOC_EXPORT
 #    ifdef DLLEXPORT
 #      define JEMALLOC_EXPORT __declspec(dllexport)
@@ -47,13 +73,30 @@
 #      define JEMALLOC_EXPORT __declspec(dllimport)
 #    endif
 #  endif
-#  define JEMALLOC_ALIGNED(s) __declspec(align(s))
-#  define JEMALLOC_SECTION(s) __declspec(allocate(s))
+#  define JEMALLOC_FORMAT_PRINTF(s, i)
 #  define JEMALLOC_NOINLINE __declspec(noinline)
+#  ifdef __cplusplus
+#    define JEMALLOC_NOTHROW __declspec(nothrow)
+#  else
+#    define JEMALLOC_NOTHROW
+#  endif
+#  define JEMALLOC_SECTION(s) __declspec(allocate(s))
+#  define JEMALLOC_RESTRICT_RETURN __declspec(restrict)
+#  if _MSC_VER >= 1900 && !defined(__EDG__)
+#    define JEMALLOC_ALLOCATOR __declspec(allocator)
+#  else
+#    define JEMALLOC_ALLOCATOR
+#  endif
 #else
 #  define JEMALLOC_ATTR(s)
-#  define JEMALLOC_EXPORT
 #  define JEMALLOC_ALIGNED(s)
-#  define JEMALLOC_SECTION(s)
+#  define JEMALLOC_ALLOC_SIZE(s)
+#  define JEMALLOC_ALLOC_SIZE2(s1, s2)
+#  define JEMALLOC_EXPORT
+#  define JEMALLOC_FORMAT_PRINTF(s, i)
 #  define JEMALLOC_NOINLINE
+#  define JEMALLOC_NOTHROW
+#  define JEMALLOC_SECTION(s)
+#  define JEMALLOC_RESTRICT_RETURN
+#  define JEMALLOC_ALLOCATOR
 #endif
diff --git a/include/jemalloc/jemalloc_protos.h b/include/jemalloc/jemalloc_protos.h
index 326a701..e8ebafc 100644
--- a/include/jemalloc/jemalloc_protos.h
+++ b/include/jemalloc/jemalloc_protos.h
@@ -7,46 +7,62 @@
 extern JEMALLOC_EXPORT void		(*je_malloc_message)(void *cbopaque,
     const char *s);
 
-JEMALLOC_EXPORT void	*je_malloc(size_t size) JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*je_calloc(size_t num, size_t size)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT int	je_posix_memalign(void **memptr, size_t alignment,
-    size_t size) JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT void	*je_aligned_alloc(size_t alignment, size_t size)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*je_realloc(void *ptr, size_t size);
-JEMALLOC_EXPORT void	je_free(void *ptr);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_malloc(size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_calloc(size_t num, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_posix_memalign(void **memptr,
+    size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1));
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_aligned_alloc(size_t alignment,
+    size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc)
+    JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_realloc(void *ptr, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_free(void *ptr)
+    JEMALLOC_CXX_THROW;
 
-JEMALLOC_EXPORT void	*je_mallocx(size_t size, int flags)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*je_rallocx(void *ptr, size_t size, int flags);
-JEMALLOC_EXPORT size_t	je_xallocx(void *ptr, size_t size, size_t extra,
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_mallocx(size_t size, int flags)
+    JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_rallocx(void *ptr, size_t size,
+    int flags) JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_xallocx(void *ptr, size_t size,
+    size_t extra, int flags);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_sallocx(const void *ptr,
+    int flags) JEMALLOC_ATTR(pure);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_dallocx(void *ptr, int flags);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_sdallocx(void *ptr, size_t size,
     int flags);
-JEMALLOC_EXPORT size_t	je_sallocx(const void *ptr, int flags)
-    JEMALLOC_ATTR(pure);
-JEMALLOC_EXPORT void	je_dallocx(void *ptr, int flags);
-JEMALLOC_EXPORT void	je_sdallocx(void *ptr, size_t size, int flags);
-JEMALLOC_EXPORT size_t	je_nallocx(size_t size, int flags)
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_nallocx(size_t size, int flags)
     JEMALLOC_ATTR(pure);
 
-JEMALLOC_EXPORT int	je_mallctl(const char *name, void *oldp,
-    size_t *oldlenp, void *newp, size_t newlen);
-JEMALLOC_EXPORT int	je_mallctlnametomib(const char *name, size_t *mibp,
-    size_t *miblenp);
-JEMALLOC_EXPORT int	je_mallctlbymib(const size_t *mib, size_t miblen,
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_mallctl(const char *name,
     void *oldp, size_t *oldlenp, void *newp, size_t newlen);
-JEMALLOC_EXPORT void	je_malloc_stats_print(void (*write_cb)(void *,
-    const char *), void *je_cbopaque, const char *opts);
-JEMALLOC_EXPORT size_t	je_malloc_usable_size(
-    JEMALLOC_USABLE_SIZE_CONST void *ptr);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_mallctlnametomib(const char *name,
+    size_t *mibp, size_t *miblenp);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	je_mallctlbymib(const size_t *mib,
+    size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	je_malloc_stats_print(
+    void (*write_cb)(void *, const char *), void *je_cbopaque,
+    const char *opts);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	je_malloc_usable_size(
+    JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW;
 
 #ifdef JEMALLOC_OVERRIDE_MEMALIGN
-JEMALLOC_EXPORT void *	je_memalign(size_t alignment, size_t size)
-    JEMALLOC_ATTR(malloc);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_memalign(size_t alignment, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc);
 #endif
 
 #ifdef JEMALLOC_OVERRIDE_VALLOC
-JEMALLOC_EXPORT void *	je_valloc(size_t size) JEMALLOC_ATTR(malloc);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*je_valloc(size_t size) JEMALLOC_CXX_THROW
+    JEMALLOC_ATTR(malloc);
 #endif
 
 typedef void *(chunk_alloc_t)(size_t, size_t, bool *, unsigned);
diff --git a/include/jemalloc/jemalloc_protos_jet.h b/include/jemalloc/jemalloc_protos_jet.h
index 495c403..23a3cde 100644
--- a/include/jemalloc/jemalloc_protos_jet.h
+++ b/include/jemalloc/jemalloc_protos_jet.h
@@ -7,46 +7,62 @@
 extern JEMALLOC_EXPORT void		(*jet_malloc_message)(void *cbopaque,
     const char *s);
 
-JEMALLOC_EXPORT void	*jet_malloc(size_t size) JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*jet_calloc(size_t num, size_t size)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT int	jet_posix_memalign(void **memptr, size_t alignment,
-    size_t size) JEMALLOC_ATTR(nonnull(1));
-JEMALLOC_EXPORT void	*jet_aligned_alloc(size_t alignment, size_t size)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*jet_realloc(void *ptr, size_t size);
-JEMALLOC_EXPORT void	jet_free(void *ptr);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_malloc(size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_calloc(size_t num, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE2(1, 2);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	jet_posix_memalign(void **memptr,
+    size_t alignment, size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(nonnull(1));
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_aligned_alloc(size_t alignment,
+    size_t size) JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc)
+    JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_realloc(void *ptr, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	jet_free(void *ptr)
+    JEMALLOC_CXX_THROW;
 
-JEMALLOC_EXPORT void	*jet_mallocx(size_t size, int flags)
-    JEMALLOC_ATTR(malloc);
-JEMALLOC_EXPORT void	*jet_rallocx(void *ptr, size_t size, int flags);
-JEMALLOC_EXPORT size_t	jet_xallocx(void *ptr, size_t size, size_t extra,
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_mallocx(size_t size, int flags)
+    JEMALLOC_ATTR(malloc) JEMALLOC_ALLOC_SIZE(1);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_rallocx(void *ptr, size_t size,
+    int flags) JEMALLOC_ALLOC_SIZE(2);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	jet_xallocx(void *ptr, size_t size,
+    size_t extra, int flags);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	jet_sallocx(const void *ptr,
+    int flags) JEMALLOC_ATTR(pure);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	jet_dallocx(void *ptr, int flags);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	jet_sdallocx(void *ptr, size_t size,
     int flags);
-JEMALLOC_EXPORT size_t	jet_sallocx(const void *ptr, int flags)
-    JEMALLOC_ATTR(pure);
-JEMALLOC_EXPORT void	jet_dallocx(void *ptr, int flags);
-JEMALLOC_EXPORT void	jet_sdallocx(void *ptr, size_t size, int flags);
-JEMALLOC_EXPORT size_t	jet_nallocx(size_t size, int flags)
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	jet_nallocx(size_t size, int flags)
     JEMALLOC_ATTR(pure);
 
-JEMALLOC_EXPORT int	jet_mallctl(const char *name, void *oldp,
-    size_t *oldlenp, void *newp, size_t newlen);
-JEMALLOC_EXPORT int	jet_mallctlnametomib(const char *name, size_t *mibp,
-    size_t *miblenp);
-JEMALLOC_EXPORT int	jet_mallctlbymib(const size_t *mib, size_t miblen,
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	jet_mallctl(const char *name,
     void *oldp, size_t *oldlenp, void *newp, size_t newlen);
-JEMALLOC_EXPORT void	jet_malloc_stats_print(void (*write_cb)(void *,
-    const char *), void *jet_cbopaque, const char *opts);
-JEMALLOC_EXPORT size_t	jet_malloc_usable_size(
-    JEMALLOC_USABLE_SIZE_CONST void *ptr);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	jet_mallctlnametomib(const char *name,
+    size_t *mibp, size_t *miblenp);
+JEMALLOC_EXPORT int JEMALLOC_NOTHROW	jet_mallctlbymib(const size_t *mib,
+    size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+JEMALLOC_EXPORT void JEMALLOC_NOTHROW	jet_malloc_stats_print(
+    void (*write_cb)(void *, const char *), void *jet_cbopaque,
+    const char *opts);
+JEMALLOC_EXPORT size_t JEMALLOC_NOTHROW	jet_malloc_usable_size(
+    JEMALLOC_USABLE_SIZE_CONST void *ptr) JEMALLOC_CXX_THROW;
 
 #ifdef JEMALLOC_OVERRIDE_MEMALIGN
-JEMALLOC_EXPORT void *	jet_memalign(size_t alignment, size_t size)
-    JEMALLOC_ATTR(malloc);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_memalign(size_t alignment, size_t size)
+    JEMALLOC_CXX_THROW JEMALLOC_ATTR(malloc);
 #endif
 
 #ifdef JEMALLOC_OVERRIDE_VALLOC
-JEMALLOC_EXPORT void *	jet_valloc(size_t size) JEMALLOC_ATTR(malloc);
+JEMALLOC_EXPORT JEMALLOC_ALLOCATOR JEMALLOC_RESTRICT_RETURN
+    void JEMALLOC_NOTHROW	*jet_valloc(size_t size) JEMALLOC_CXX_THROW
+    JEMALLOC_ATTR(malloc);
 #endif
 
 typedef void *(chunk_alloc_t)(size_t, size_t, bool *, unsigned);
diff --git a/include/jemalloc/jemalloc_typedefs.h b/include/jemalloc/jemalloc_typedefs.h
index d4b4690..fa7b350 100644
--- a/include/jemalloc/jemalloc_typedefs.h
+++ b/include/jemalloc/jemalloc_typedefs.h
@@ -1,3 +1,57 @@
-typedef void *(chunk_alloc_t)(void *, size_t, size_t, bool *, unsigned);
-typedef bool (chunk_dalloc_t)(void *, size_t, unsigned);
-typedef bool (chunk_purge_t)(void *, size_t, size_t, unsigned);
+/*
+ * void *
+ * chunk_alloc(void *new_addr, size_t size, size_t alignment, bool *zero,
+ *     bool *commit, unsigned arena_ind);
+ */
+typedef void *(chunk_alloc_t)(void *, size_t, size_t, bool *, bool *, unsigned);
+
+/*
+ * bool
+ * chunk_dalloc(void *chunk, size_t size, bool committed, unsigned arena_ind);
+ */
+typedef bool (chunk_dalloc_t)(void *, size_t, bool, unsigned);
+
+/*
+ * bool
+ * chunk_commit(void *chunk, size_t size, size_t offset, size_t length,
+ *     unsigned arena_ind);
+ */
+typedef bool (chunk_commit_t)(void *, size_t, size_t, size_t, unsigned);
+
+/*
+ * bool
+ * chunk_decommit(void *chunk, size_t size, size_t offset, size_t length,
+ *     unsigned arena_ind);
+ */
+typedef bool (chunk_decommit_t)(void *, size_t, size_t, size_t, unsigned);
+
+/*
+ * bool
+ * chunk_purge(void *chunk, size_t size, size_t offset, size_t length,
+ *     unsigned arena_ind);
+ */
+typedef bool (chunk_purge_t)(void *, size_t, size_t, size_t, unsigned);
+
+/*
+ * bool
+ * chunk_split(void *chunk, size_t size, size_t size_a, size_t size_b,
+ *     bool committed, unsigned arena_ind);
+ */
+typedef bool (chunk_split_t)(void *, size_t, size_t, size_t, bool, unsigned);
+
+/*
+ * bool
+ * chunk_merge(void *chunk_a, size_t size_a, void *chunk_b, size_t size_b,
+ *     bool committed, unsigned arena_ind);
+ */
+typedef bool (chunk_merge_t)(void *, size_t, void *, size_t, bool, unsigned);
+
+typedef struct {
+	chunk_alloc_t		*alloc;
+	chunk_dalloc_t		*dalloc;
+	chunk_commit_t		*commit;
+	chunk_decommit_t	*decommit;
+	chunk_purge_t		*purge;
+	chunk_split_t		*split;
+	chunk_merge_t		*merge;
+} chunk_hooks_t;
diff --git a/src/android_je_mallinfo.c b/src/android_je_mallinfo.c
new file mode 100644
index 0000000..1637edd
--- /dev/null
+++ b/src/android_je_mallinfo.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is an implementation that uses the same arena access pattern found
+ * in the arena_stats_merge function from src/arena.c.
+ */
+struct mallinfo je_mallinfo() {
+  struct mallinfo mi;
+  memset(&mi, 0, sizeof(mi));
+
+  malloc_mutex_lock(&arenas_lock);
+  for (unsigned i = 0; i < narenas_auto; i++) {
+    if (arenas[i] != NULL) {
+      malloc_mutex_lock(&arenas[i]->lock);
+      mi.hblkhd += arenas[i]->stats.mapped;
+      mi.uordblks += arenas[i]->stats.allocated_large;
+      mi.uordblks += arenas[i]->stats.allocated_huge;
+      malloc_mutex_unlock(&arenas[i]->lock);
+
+      for (unsigned j = 0; j < NBINS; j++) {
+        arena_bin_t* bin = &arenas[i]->bins[j];
+
+        malloc_mutex_lock(&bin->lock);
+        mi.uordblks += arena_bin_info[j].reg_size * bin->stats.curregs;
+        malloc_mutex_unlock(&bin->lock);
+      }
+    }
+  }
+  malloc_mutex_unlock(&arenas_lock);
+  mi.fordblks = mi.hblkhd - mi.uordblks;
+  mi.usmblks = mi.hblkhd;
+  return mi;
+}
+
+size_t __mallinfo_narenas() {
+  return narenas_auto;
+}
+
+size_t __mallinfo_nbins() {
+  return NBINS;
+}
+
+struct mallinfo __mallinfo_arena_info(size_t aidx) {
+  struct mallinfo mi;
+  memset(&mi, 0, sizeof(mi));
+
+  malloc_mutex_lock(&arenas_lock);
+  if (aidx < narenas_auto) {
+    if (arenas[aidx] != NULL) {
+      malloc_mutex_lock(&arenas[aidx]->lock);
+      mi.hblkhd = arenas[aidx]->stats.mapped;
+      mi.ordblks = arenas[aidx]->stats.allocated_large;
+      mi.uordblks = arenas[aidx]->stats.allocated_huge;
+      malloc_mutex_unlock(&arenas[aidx]->lock);
+
+      for (unsigned j = 0; j < NBINS; j++) {
+        arena_bin_t* bin = &arenas[aidx]->bins[j];
+
+        malloc_mutex_lock(&bin->lock);
+        mi.fsmblks += arena_bin_info[j].reg_size * bin->stats.curregs;
+        malloc_mutex_unlock(&bin->lock);
+      }
+    }
+  }
+  malloc_mutex_unlock(&arenas_lock);
+  return mi;
+}
+
+struct mallinfo __mallinfo_bin_info(size_t aidx, size_t bidx) {
+  struct mallinfo mi;
+  memset(&mi, 0, sizeof(mi));
+
+  malloc_mutex_lock(&arenas_lock);
+  if (aidx < narenas_auto && bidx < NBINS) {
+    if (arenas[aidx] != NULL) {
+      arena_bin_t* bin = &arenas[aidx]->bins[bidx];
+
+      malloc_mutex_lock(&bin->lock);
+      mi.ordblks = arena_bin_info[bidx].reg_size * bin->stats.curregs;
+      mi.uordblks = bin->stats.nmalloc;
+      mi.fordblks = bin->stats.ndalloc;
+      malloc_mutex_unlock(&bin->lock);
+    }
+  }
+  malloc_mutex_unlock(&arenas_lock);
+  return mi;
+}
diff --git a/src/arena.c b/src/arena.c
index 949fc5b..07d83ef 100644
--- a/src/arena.c
+++ b/src/arena.c
@@ -1207,10 +1207,13 @@
 void
 arena_maybe_purge(arena_t *arena)
 {
-
+#if defined(ANDROID_ALWAYS_PURGE)
+	size_t num_tries = 0;
+#else
 	/* Don't purge if the option is disabled. */
 	if (arena->lg_dirty_mult < 0)
 		return;
+#endif
 	/* Don't recursively purge. */
 	if (arena->purging)
 		return;
@@ -1219,6 +1222,10 @@
 	 * many dirty pages.
 	 */
 	while (true) {
+#if defined(ANDROID_ALWAYS_PURGE)
+		if (arena->ndirty == 0 || ++num_tries == 3)
+			return;
+#else
 		size_t threshold = (arena->nactive >> arena->lg_dirty_mult);
 		if (threshold < chunk_npages)
 			threshold = chunk_npages;
@@ -1228,6 +1235,7 @@
 		 */
 		if (arena->ndirty <= threshold)
 			return;
+#endif
 		arena_purge(arena, false);
 	}
 }
diff --git a/src/jemalloc.c b/src/jemalloc.c
index 7cf1487..8e56bb0 100644
--- a/src/jemalloc.c
+++ b/src/jemalloc.c
@@ -864,7 +864,11 @@
 			opt_tcache = false;
 	}
 
+#if defined(__ANDROID__)
+	for (i = 0; i < 1; i++) {
+#else
 	for (i = 0; i < 3; i++) {
+#endif
 		/* Get runtime configuration. */
 		switch (i) {
 		case 0:
@@ -1278,6 +1282,14 @@
 		else
 			opt_narenas = 1;
 	}
+#if defined(ANDROID_MAX_ARENAS)
+	/* Never create more than MAX_ARENAS arenas regardless of num_cpus.
+	 * Extra arenas use more PSS and are not very useful unless
+	 * lots of threads are allocing/freeing at the same time.
+	 */
+	if (opt_narenas > ANDROID_MAX_ARENAS)
+		opt_narenas = ANDROID_MAX_ARENAS;
+#endif
 	narenas_auto = opt_narenas;
 	/*
 	 * Make sure that the arenas array can be allocated.  In practice, this
@@ -2593,3 +2605,7 @@
 }
 
 /******************************************************************************/
+
+/* ANDROID extension */
+#include "android_je_mallinfo.c"
+/* End ANDROID extension */
diff --git a/src/pages.c b/src/pages.c
index 83a167f..993c0a6 100644
--- a/src/pages.c
+++ b/src/pages.c
@@ -2,6 +2,17 @@
 #include "jemalloc/internal/jemalloc_internal.h"
 
 /******************************************************************************/
+/* Defines/includes needed for special android code. */
+
+#if defined(__ANDROID__)
+#include <sys/prctl.h>
+
+/* Definitions of prctl arguments to set a vma name in Android kernels. */
+#define ANDROID_PR_SET_VMA            0x53564d41
+#define ANDROID_PR_SET_VMA_ANON_NAME  0
+#endif
+
+/******************************************************************************/
 
 void *
 pages_map(void *addr, size_t size)
@@ -36,6 +47,13 @@
 		ret = NULL;
 	}
 #endif
+#if defined(__ANDROID__)
+	if (ret != NULL) {
+		/* Name this memory as being used by libc */
+		prctl(ANDROID_PR_SET_VMA, ANDROID_PR_SET_VMA_ANON_NAME, ret,
+		    size, "libc_malloc");
+	}
+#endif
 	assert(ret == NULL || (addr == NULL && ret != addr)
 	    || (addr != NULL && ret == addr));
 	return (ret);
diff --git a/test/include/test/jemalloc_test.h b/test/include/test/jemalloc_test.h
index ba72a6f..1d9a756 100644
--- a/test/include/test/jemalloc_test.h
+++ b/test/include/test/jemalloc_test.h
@@ -1,14 +1,21 @@
+#include <limits.h>
+#ifndef SIZE_T_MAX
+#  define SIZE_T_MAX	SIZE_MAX
+#endif
 #include <stdlib.h>
 #include <stdarg.h>
 #include <stdbool.h>
 #include <errno.h>
-#include <inttypes.h>
 #include <math.h>
 #include <string.h>
+#ifdef _WIN32
+#  include "msvc_compat/strings.h"
+#endif
 #include <sys/time.h>
 
 #ifdef _WIN32
 #  include <windows.h>
+#  include "msvc_compat/windows_extra.h"
 #else
 #  include <pthread.h>
 #endif