Bug 1343432 - Update jemalloc 4 to version 4.5.0. r=glandium
☠☠ backed out by 49e60602adda ☠ ☠
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 01 Mar 2017 21:06:24 -0500
changeset 394526 24bea8bde57dcc65ff50b0f349134231372a9091
parent 394525 7ab155596912494146faebc0ce30b542e2b730fa
child 394527 30dc81445a1b3c927af48b3522bd14a0cfe501d4
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs1343432
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1343432 - Update jemalloc 4 to version 4.5.0. r=glandium
memory/jemalloc/src/.appveyor.yml
memory/jemalloc/src/.travis.yml
memory/jemalloc/src/ChangeLog
memory/jemalloc/src/INSTALL
memory/jemalloc/src/Makefile.in
memory/jemalloc/src/VERSION
memory/jemalloc/src/configure
memory/jemalloc/src/configure.ac
memory/jemalloc/src/doc/jemalloc.xml.in
memory/jemalloc/src/include/jemalloc/internal/arena.h
memory/jemalloc/src/include/jemalloc/internal/chunk.h
memory/jemalloc/src/include/jemalloc/internal/extent.h
memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal.h.in
memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal_defs.h.in
memory/jemalloc/src/include/jemalloc/internal/mutex.h
memory/jemalloc/src/include/jemalloc/internal/private_symbols.txt
memory/jemalloc/src/include/jemalloc/internal/tcache.h
memory/jemalloc/src/include/jemalloc/internal/tsd.h
memory/jemalloc/src/include/jemalloc/internal/witness.h
memory/jemalloc/src/msvc/projects/vc2015/test_threads/test_threads.cpp
memory/jemalloc/src/scripts/gen_travis.py
memory/jemalloc/src/src/arena.c
memory/jemalloc/src/src/chunk.c
memory/jemalloc/src/src/chunk_dss.c
memory/jemalloc/src/src/ctl.c
memory/jemalloc/src/src/extent.c
memory/jemalloc/src/src/huge.c
memory/jemalloc/src/src/jemalloc.c
memory/jemalloc/src/src/pages.c
memory/jemalloc/src/src/stats.c
memory/jemalloc/src/src/tcache.c
memory/jemalloc/src/src/util.c
memory/jemalloc/src/src/witness.c
memory/jemalloc/src/test/integration/MALLOCX_ARENA.c
memory/jemalloc/src/test/integration/allocated.c
memory/jemalloc/src/test/integration/chunk.c
memory/jemalloc/src/test/integration/chunk.sh
memory/jemalloc/src/test/integration/mallocx.c
memory/jemalloc/src/test/integration/mallocx.sh
memory/jemalloc/src/test/integration/overflow.c
memory/jemalloc/src/test/integration/rallocx.c
memory/jemalloc/src/test/integration/thread_arena.c
memory/jemalloc/src/test/integration/thread_tcache_enabled.c
memory/jemalloc/src/test/integration/xallocx.c
memory/jemalloc/src/test/integration/xallocx.sh
memory/jemalloc/src/test/test.sh.in
memory/jemalloc/src/test/unit/arena_reset.c
memory/jemalloc/src/test/unit/arena_reset.sh
memory/jemalloc/src/test/unit/decay.c
memory/jemalloc/src/test/unit/decay.sh
memory/jemalloc/src/test/unit/extent_quantize.c
memory/jemalloc/src/test/unit/junk.c
memory/jemalloc/src/test/unit/junk.sh
memory/jemalloc/src/test/unit/junk_alloc.c
memory/jemalloc/src/test/unit/junk_alloc.sh
memory/jemalloc/src/test/unit/junk_free.c
memory/jemalloc/src/test/unit/junk_free.sh
memory/jemalloc/src/test/unit/lg_chunk.c
memory/jemalloc/src/test/unit/lg_chunk.sh
memory/jemalloc/src/test/unit/mallctl.c
memory/jemalloc/src/test/unit/pack.c
memory/jemalloc/src/test/unit/pack.sh
memory/jemalloc/src/test/unit/prof_accum.c
memory/jemalloc/src/test/unit/prof_accum.sh
memory/jemalloc/src/test/unit/prof_active.c
memory/jemalloc/src/test/unit/prof_active.sh
memory/jemalloc/src/test/unit/prof_gdump.c
memory/jemalloc/src/test/unit/prof_gdump.sh
memory/jemalloc/src/test/unit/prof_idump.c
memory/jemalloc/src/test/unit/prof_idump.sh
memory/jemalloc/src/test/unit/prof_reset.c
memory/jemalloc/src/test/unit/prof_reset.sh
memory/jemalloc/src/test/unit/prof_tctx.sh
memory/jemalloc/src/test/unit/prof_thread_name.c
memory/jemalloc/src/test/unit/prof_thread_name.sh
memory/jemalloc/src/test/unit/quarantine.c
memory/jemalloc/src/test/unit/quarantine.sh
memory/jemalloc/src/test/unit/size_classes.c
memory/jemalloc/src/test/unit/stats.c
memory/jemalloc/src/test/unit/stats_print.c
memory/jemalloc/src/test/unit/witness.c
memory/jemalloc/src/test/unit/zero.c
memory/jemalloc/src/test/unit/zero.sh
memory/jemalloc/upstream.info
--- a/memory/jemalloc/src/.appveyor.yml
+++ b/memory/jemalloc/src/.appveyor.yml
@@ -7,22 +7,36 @@ environment:
     MSVC: amd64
   - MSYSTEM: MINGW32
     CPU: i686
     MSVC: x86
   - MSYSTEM: MINGW64
     CPU: x86_64
   - MSYSTEM: MINGW32
     CPU: i686
+  - MSYSTEM: MINGW64
+    CPU: x86_64
+    MSVC: amd64
+    CONFIG_FLAGS: --enable-debug
+  - MSYSTEM: MINGW32
+    CPU: i686
+    MSVC: x86
+    CONFIG_FLAGS: --enable-debug
+  - MSYSTEM: MINGW64
+    CPU: x86_64
+    CONFIG_FLAGS: --enable-debug
+  - MSYSTEM: MINGW32
+    CPU: i686
+    CONFIG_FLAGS: --enable-debug
 
 install:
   - set PATH=c:\msys64\%MSYSTEM%\bin;c:\msys64\usr\bin;%PATH%
   - if defined MSVC call "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %MSVC%
   - if defined MSVC pacman --noconfirm -Rsc mingw-w64-%CPU%-gcc gcc
   - pacman --noconfirm -Suy mingw-w64-%CPU%-make
 
 build_script:
   - bash -c "autoconf"
-  - bash -c "./configure"
+  - bash -c "./configure $CONFIG_FLAGS"
   - mingw32-make -j3
   - file lib/jemalloc.dll
   - mingw32-make -j3 tests
   - mingw32-make -k check
--- a/memory/jemalloc/src/.travis.yml
+++ b/memory/jemalloc/src/.travis.yml
@@ -1,29 +1,95 @@
-language: c
+language: generic
 
 matrix:
   include:
     - os: linux
-      compiler: gcc
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS=""
+    - os: osx
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS=""
+    - os: linux
+      env: CC=clang COMPILER_FLAGS="" CONFIGURE_FLAGS=""
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="-m32" CONFIGURE_FLAGS=""
+      addons:
+        apt:
+          packages:
+            - gcc-multilib
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof"
     - os: linux
-      compiler: gcc
-      env:
-        - EXTRA_FLAGS=-m32
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-tcache"
+    - os: osx
+      env: CC=clang COMPILER_FLAGS="" CONFIGURE_FLAGS=""
+    - os: osx
+      env: CC=gcc COMPILER_FLAGS="-m32" CONFIGURE_FLAGS=""
+    - os: osx
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug"
+    - os: osx
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats"
+    - os: osx
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-tcache"
+    - os: linux
+      env: CC=clang COMPILER_FLAGS="-m32" CONFIGURE_FLAGS=""
       addons:
         apt:
           packages:
-          - gcc-multilib
-    - os: osx
-      compiler: clang
-    - os: osx
-      compiler: clang
-      env:
-        - EXTRA_FLAGS=-m32
+            - gcc-multilib
+    - os: linux
+      env: CC=clang COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug"
+    - os: linux
+      env: CC=clang COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof"
+    - os: linux
+      env: CC=clang COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats"
+    - os: linux
+      env: CC=clang COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-tcache"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--enable-debug"
+      addons:
+        apt:
+          packages:
+            - gcc-multilib
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--enable-prof"
+      addons:
+        apt:
+          packages:
+            - gcc-multilib
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--disable-stats"
+      addons:
+        apt:
+          packages:
+            - gcc-multilib
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="-m32" CONFIGURE_FLAGS="--disable-tcache"
+      addons:
+        apt:
+          packages:
+            - gcc-multilib
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --enable-prof"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --disable-stats"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-debug --disable-tcache"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof --disable-stats"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--enable-prof --disable-tcache"
+    - os: linux
+      env: CC=gcc COMPILER_FLAGS="" CONFIGURE_FLAGS="--disable-stats --disable-tcache"
+
 
 before_script:
   - autoconf
-  - ./configure${EXTRA_FLAGS:+ CC="$CC $EXTRA_FLAGS"}
+  - ./configure ${COMPILER_FLAGS:+       CC="$CC $COMPILER_FLAGS" }       $CONFIGURE_FLAGS
   - make -j3
   - make -j3 tests
 
 script:
   - make check
+
--- a/memory/jemalloc/src/ChangeLog
+++ b/memory/jemalloc/src/ChangeLog
@@ -1,14 +1,49 @@
 Following are change highlights associated with official releases.  Important
 bug fixes are all mentioned, but some internal enhancements are omitted here for
 brevity.  Much more detail can be found in the git revision history:
 
     https://github.com/jemalloc/jemalloc
 
+* 4.5.0 (February 28, 2017)
+
+  This is the first release to benefit from much broader continuous integration
+  testing, thanks to @davidtgoldblatt.  Had we had this testing infrastructure
+  in place for prior releases, it would have caught all of the most serious
+  regressions fixed by this release.
+
+  New features:
+  - Add --disable-thp and the opt.thp to provide opt-out mechanisms for
+    transparent huge page integration.  (@jasone)
+  - Update zone allocator integration to work with macOS 10.12.  (@glandium)
+  - Restructure *CFLAGS configuration, so that CFLAGS behaves typically, and
+    EXTRA_CFLAGS provides a way to specify e.g. -Werror during building, but not
+    during configuration.  (@jasone, @ronawho)
+
+  Bug fixes:
+  - Fix DSS (sbrk(2)-based) allocation.  This regression was first released in
+    4.3.0.  (@jasone)
+  - Handle race in per size class utilization computation.  This functionality
+    was first released in 4.0.0.  (@interwq)
+  - Fix lock order reversal during gdump.  (@jasone)
+  - Fix-refactor tcache synchronization.  This regression was first released in
+    4.0.0.  (@jasone)
+  - Fix various JSON-formatted malloc_stats_print() bugs.  This functionality
+    was first released in 4.3.0.  (@jasone)
+  - Fix huge-aligned allocation.  This regression was first released in 4.4.0.
+    (@jasone)
+  - When transparent huge page integration is enabled, detect what state pages
+    start in according to the kernel's current operating mode, and only convert
+    arena chunks to non-huge during purging if that is not their initial state.
+    This functionality was first released in 4.4.0.  (@jasone)
+  - Fix lg_chunk clamping for the --enable-cache-oblivious --disable-fill case.
+    This regression was first released in 4.0.0.  (@jasone, @428desmo)
+  - Properly detect sparc64 when building for Linux.  (@glaubitz)
+
 * 4.4.0 (December 3, 2016)
 
   New features:
   - Add configure support for *-*-linux-android.  (@cferris1000, @jasone)
   - Add the --disable-syscall configure option, for use on systems that place
     security-motivated limitations on syscall(2).  (@jasone)
   - Add support for Debian GNU/kFreeBSD.  (@thesam)
 
--- a/memory/jemalloc/src/INSTALL
+++ b/memory/jemalloc/src/INSTALL
@@ -152,16 +152,23 @@ any of the following arguments (not a de
     Statically link against the specified libunwind.a rather than dynamically
     linking with -lunwind.
 
 --disable-tcache
     Disable thread-specific caches for small objects.  Objects are cached and
     released in bulk, thus reducing the total number of mutex operations.  See
     the "opt.tcache" option for usage details.
 
+--disable-thp
+    Disable transparent huge page (THP) integration.  On systems with THP
+    support, THPs are explicitly disabled as a side effect of unused dirty page
+    purging for chunks that back small and/or large allocations, because such
+    chunks typically comprise active, unused dirty, and untouched clean
+    pages.
+
 --disable-munmap
     Disable virtual memory deallocation via munmap(2); instead keep track of
     the virtual memory for later use.  munmap() is disabled by default (i.e.
     --disable-munmap is implied) on Linux, which has a quirk in its virtual
     memory allocation algorithm that causes semi-permanent VM map holes under
     normal jemalloc operation.
 
 --disable-fill
@@ -301,27 +308,26 @@ any of the following arguments (not a de
     This option is rarely useful, and is mainly provided as documentation of a
     subtle implementation detail.  If you do use this option, specify a
     value in [3, ..., <lg-quantum>].
 
 The following environment variables (not a definitive list) impact configure's
 behavior:
 
 CFLAGS="?"
-    Pass these flags to the compiler.  You probably shouldn't define this unless
-    you know what you are doing.  (Use EXTRA_CFLAGS instead.)
+    Pass these flags to the C compiler.  Any flags set by the configure script
+    are prepended, which means explicitly set flags generally take precedence.
+    Take care when specifying flags such as -Werror, because configure tests may
+    be affected in undesirable ways.
 
 EXTRA_CFLAGS="?"
-    Append these flags to CFLAGS.  This makes it possible to add flags such as
-    -Werror, while allowing the configure script to determine what other flags
-    are appropriate for the specified configuration.
-
-    The configure script specifically checks whether an optimization flag (-O*)
-    is specified in EXTRA_CFLAGS, and refrains from specifying an optimization
-    level if it finds that one has already been specified.
+    Append these flags to CFLAGS, without passing them to the compiler during
+    configuration.  This makes it possible to add flags such as -Werror, while
+    allowing the configure script to determine what other flags are appropriate
+    for the specified configuration.
 
 CPPFLAGS="?"
     Pass these flags to the C preprocessor.  Note that CFLAGS is not passed to
     'cpp' when 'configure' is looking for include files, so you must use
     CPPFLAGS instead if you need to help 'configure' find header files.
 
 LD_LIBRARY_PATH="?"
     'ld' uses this colon-separated list to find libraries.
--- a/memory/jemalloc/src/Makefile.in
+++ b/memory/jemalloc/src/Makefile.in
@@ -19,18 +19,20 @@ DATADIR := $(DESTDIR)@DATADIR@
 MANDIR := $(DESTDIR)@MANDIR@
 srcroot := @srcroot@
 objroot := @objroot@
 abs_srcroot := @abs_srcroot@
 abs_objroot := @abs_objroot@
 
 # Build parameters.
 CPPFLAGS := @CPPFLAGS@ -I$(srcroot)include -I$(objroot)include
+CONFIGURE_CFLAGS := @CONFIGURE_CFLAGS@
+SPECIFIED_CFLAGS := @SPECIFIED_CFLAGS@
 EXTRA_CFLAGS := @EXTRA_CFLAGS@
-CFLAGS := @CFLAGS@ $(EXTRA_CFLAGS)
+CFLAGS := $(strip $(CONFIGURE_CFLAGS) $(SPECIFIED_CFLAGS) $(EXTRA_CFLAGS))
 LDFLAGS := @LDFLAGS@
 EXTRA_LDFLAGS := @EXTRA_LDFLAGS@
 LIBS := @LIBS@
 RPATH_EXTRA := @RPATH_EXTRA@
 SO := @so@
 IMPORTLIB := @importlib@
 O := @o@
 A := @a@
@@ -151,16 +153,17 @@ C_UTIL_INTEGRATION_SRCS := $(srcroot)src
 endif
 TESTS_UNIT := \
 	$(srcroot)test/unit/a0.c \
 	$(srcroot)test/unit/arena_reset.c \
 	$(srcroot)test/unit/atomic.c \
 	$(srcroot)test/unit/bitmap.c \
 	$(srcroot)test/unit/ckh.c \
 	$(srcroot)test/unit/decay.c \
+	$(srcroot)test/unit/extent_quantize.c \
 	$(srcroot)test/unit/fork.c \
 	$(srcroot)test/unit/hash.c \
 	$(srcroot)test/unit/junk.c \
 	$(srcroot)test/unit/junk_alloc.c \
 	$(srcroot)test/unit/junk_free.c \
 	$(srcroot)test/unit/lg_chunk.c \
 	$(srcroot)test/unit/mallctl.c \
 	$(srcroot)test/unit/math.c \
@@ -181,16 +184,17 @@ TESTS_UNIT := \
 	$(srcroot)test/unit/quarantine.c \
 	$(srcroot)test/unit/rb.c \
 	$(srcroot)test/unit/rtree.c \
 	$(srcroot)test/unit/run_quantize.c \
 	$(srcroot)test/unit/SFMT.c \
 	$(srcroot)test/unit/size_classes.c \
 	$(srcroot)test/unit/smoothstep.c \
 	$(srcroot)test/unit/stats.c \
+	$(srcroot)test/unit/stats_print.c \
 	$(srcroot)test/unit/ticker.c \
 	$(srcroot)test/unit/nstime.c \
 	$(srcroot)test/unit/tsd.c \
 	$(srcroot)test/unit/util.c \
 	$(srcroot)test/unit/witness.c \
 	$(srcroot)test/unit/zero.c
 TESTS_INTEGRATION := $(srcroot)test/integration/aligned_alloc.c \
 	$(srcroot)test/integration/allocated.c \
--- a/memory/jemalloc/src/VERSION
+++ b/memory/jemalloc/src/VERSION
@@ -1,1 +1,1 @@
-4.4.0-3-gc6943acb3c56d1b3d1e82dd43b3fcfeae7771990
+4.5.0-0-g04380e79f1e2428bd0ad000bbc6e3d2dfc6b66a5
--- a/memory/jemalloc/src/configure
+++ b/memory/jemalloc/src/configure
@@ -621,16 +621,17 @@ ac_includes_default="\
 
 ac_subst_vars='LTLIBOBJS
 LIBOBJS
 cfgoutputs_out
 cfgoutputs_in
 cfghdrs_out
 cfghdrs_in
 enable_zone_allocator
+enable_thp
 enable_tls
 enable_lazy_lock
 jemalloc_version_gid
 jemalloc_version_nrev
 jemalloc_version_bugfix
 jemalloc_version_minor
 jemalloc_version_major
 jemalloc_version
@@ -687,16 +688,18 @@ host
 build_os
 build_vendor
 build_cpu
 build
 EGREP
 GREP
 CPP
 EXTRA_CFLAGS
+SPECIFIED_CFLAGS
+CONFIGURE_CFLAGS
 OBJEXT
 EXEEXT
 ac_ct_CC
 CPPFLAGS
 LDFLAGS
 CFLAGS
 CC
 XSLROOT
@@ -785,16 +788,17 @@ with_lg_tiny_min
 with_lg_quantum
 with_lg_page
 with_lg_page_sizes
 with_lg_size_class_group
 with_version
 enable_syscall
 enable_lazy_lock
 enable_tls
+enable_thp
 enable_zone_allocator
 '
       ac_precious_vars='build_alias
 host_alias
 target_alias
 CC
 CFLAGS
 LDFLAGS
@@ -1441,16 +1445,17 @@ Optional Features:
   --disable-valgrind      Disable support for Valgrind
   --enable-xmalloc        Support xmalloc option
   --disable-cache-oblivious
                           Disable support for cache-oblivious allocation
                           alignment
   --disable-syscall       Disable use of syscall(2)
   --enable-lazy-lock      Enable lazy locking (only lock when multi-threaded)
   --disable-tls           Disable thread-local storage (__thread keyword)
+  --disable-thp           Disable transparent huge page supprot
   --disable-zone-allocator
                           Disable zone allocator for Darwin
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
   --with-xslroot=<path>   XSL stylesheet root path
   --with-rpath=<rpath>    Colon-separated rpath (ELF systems only)
@@ -2537,16 +2542,25 @@ ac_configure="$SHELL $ac_aux_dir/configu
 
 
 
 
 
 
 
 
+CONFIGURE_CFLAGS=
+SPECIFIED_CFLAGS="${CFLAGS}"
+
+
+
+
+
+
+
 
 CONFIG=`echo ${ac_configure_args} | sed -e 's#'"'"'\([^ ]*\)'"'"'#\1#g'`
 
 
 rev=2
 
 
 srcroot=$srcdir
@@ -3545,620 +3559,866 @@ else
   je_cv_cray_84=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_cray_84" >&5
 $as_echo "$je_cv_cray_84" >&6; }
 fi
 
-if test "x$CFLAGS" = "x" ; then
-  no_CFLAGS="yes"
-  if test "x$GCC" = "xyes" ; then
+if test "x$GCC" = "xyes" ; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -std=gnu11" >&5
 $as_echo_n "checking whether compiler supports -std=gnu11... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-std=gnu11"
-else
-  CFLAGS="${CFLAGS} -std=gnu11"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-std=gnu11
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-std=gnu11
+  je_cv_cflags_added=-std=gnu11
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-    if test "x$je_cv_cflags_appended" = "x-std=gnu11" ; then
-      cat >>confdefs.h <<_ACEOF
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
+  if test "x$je_cv_cflags_added" = "x-std=gnu11" ; then
+    cat >>confdefs.h <<_ACEOF
 #define JEMALLOC_HAS_RESTRICT 1
 _ACEOF
 
-    else
+  else
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -std=gnu99" >&5
 $as_echo_n "checking whether compiler supports -std=gnu99... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-std=gnu99"
-else
-  CFLAGS="${CFLAGS} -std=gnu99"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-std=gnu99
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-std=gnu99
+  je_cv_cflags_added=-std=gnu99
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-      if test "x$je_cv_cflags_appended" = "x-std=gnu99" ; then
-        cat >>confdefs.h <<_ACEOF
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
+    if test "x$je_cv_cflags_added" = "x-std=gnu99" ; then
+      cat >>confdefs.h <<_ACEOF
 #define JEMALLOC_HAS_RESTRICT 1
 _ACEOF
 
-      fi
     fi
+  fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wall" >&5
 $as_echo_n "checking whether compiler supports -Wall... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Wall"
-else
-  CFLAGS="${CFLAGS} -Wall"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Wall
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Wall
+  je_cv_cflags_added=-Wall
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror=declaration-after-statement" >&5
 $as_echo_n "checking whether compiler supports -Werror=declaration-after-statement... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Werror=declaration-after-statement"
-else
-  CFLAGS="${CFLAGS} -Werror=declaration-after-statement"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Werror=declaration-after-statement
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Werror=declaration-after-statement
+  je_cv_cflags_added=-Werror=declaration-after-statement
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wshorten-64-to-32" >&5
 $as_echo_n "checking whether compiler supports -Wshorten-64-to-32... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Wshorten-64-to-32"
-else
-  CFLAGS="${CFLAGS} -Wshorten-64-to-32"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Wshorten-64-to-32
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Wshorten-64-to-32
+  je_cv_cflags_added=-Wshorten-64-to-32
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wsign-compare" >&5
 $as_echo_n "checking whether compiler supports -Wsign-compare... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Wsign-compare"
-else
-  CFLAGS="${CFLAGS} -Wsign-compare"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Wsign-compare
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Wsign-compare
+  je_cv_cflags_added=-Wsign-compare
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -pipe" >&5
 $as_echo_n "checking whether compiler supports -pipe... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-pipe"
-else
-  CFLAGS="${CFLAGS} -pipe"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-pipe
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-pipe
+  je_cv_cflags_added=-pipe
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -g3" >&5
 $as_echo_n "checking whether compiler supports -g3... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-g3"
-else
-  CFLAGS="${CFLAGS} -g3"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-g3
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-g3
+  je_cv_cflags_added=-g3
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-  elif test "x$je_cv_msvc" = "xyes" ; then
-    CC="$CC -nologo"
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
+elif test "x$je_cv_msvc" = "xyes" ; then
+  CC="$CC -nologo"
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Zi" >&5
 $as_echo_n "checking whether compiler supports -Zi... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Zi"
-else
-  CFLAGS="${CFLAGS} -Zi"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Zi
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Zi
+  je_cv_cflags_added=-Zi
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -MT" >&5
 $as_echo_n "checking whether compiler supports -MT... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-MT"
-else
-  CFLAGS="${CFLAGS} -MT"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-MT
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-MT
+  je_cv_cflags_added=-MT
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -W3" >&5
 $as_echo_n "checking whether compiler supports -W3... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-W3"
-else
-  CFLAGS="${CFLAGS} -W3"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-W3
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-W3
+  je_cv_cflags_added=-W3
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -FS" >&5
 $as_echo_n "checking whether compiler supports -FS... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-FS"
-else
-  CFLAGS="${CFLAGS} -FS"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-FS
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-FS
+  je_cv_cflags_added=-FS
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-    CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat"
-  fi
-  if test "x$je_cv_cray" = "xyes" ; then
-        if test "x$je_cv_cray_84" = "xyes" ; then
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
+  T_APPEND_V=-I${srcdir}/include/msvc_compat
+  if test "x${CPPFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CPPFLAGS="${CPPFLAGS}${T_APPEND_V}"
+else
+  CPPFLAGS="${CPPFLAGS} ${T_APPEND_V}"
+fi
+
+
+fi
+if test "x$je_cv_cray" = "xyes" ; then
+    if test "x$je_cv_cray_84" = "xyes" ; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -hipa2" >&5
 $as_echo_n "checking whether compiler supports -hipa2... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-hipa2"
-else
-  CFLAGS="${CFLAGS} -hipa2"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-hipa2
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-hipa2
+  je_cv_cflags_added=-hipa2
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -hnognu" >&5
 $as_echo_n "checking whether compiler supports -hnognu... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-hnognu"
-else
-  CFLAGS="${CFLAGS} -hnognu"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-hnognu
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-hnognu
+  je_cv_cflags_added=-hnognu
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-    fi
-    if test "x$enable_cc_silence" != "xno" ; then
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
+  fi
+  if test "x$enable_cc_silence" != "xno" ; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -hnomessage=128" >&5
 $as_echo_n "checking whether compiler supports -hnomessage=128... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-hnomessage=128"
-else
-  CFLAGS="${CFLAGS} -hnomessage=128"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-hnomessage=128
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-hnomessage=128
+  je_cv_cflags_added=-hnomessage=128
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -hnomessage=1357" >&5
 $as_echo_n "checking whether compiler supports -hnomessage=1357... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-hnomessage=1357"
-else
-  CFLAGS="${CFLAGS} -hnomessage=1357"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-hnomessage=1357
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-hnomessage=1357
+  je_cv_cflags_added=-hnomessage=1357
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-    fi
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
   fi
 fi
 
+
+
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
 ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
 $as_echo_n "checking how to run the C preprocessor... " >&6; }
 # On Suns, sometimes $CPP names a directory.
@@ -4778,17 +5038,24 @@ fi
 if test "x${ac_cv_big_endian}" = "x1" ; then
   cat >>confdefs.h <<_ACEOF
 #define JEMALLOC_BIG_ENDIAN
 _ACEOF
 
 fi
 
 if test "x${je_cv_msvc}" = "xyes" -a "x${ac_cv_header_inttypes_h}" = "xno"; then
-  CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat/C99"
+  T_APPEND_V=-I${srcdir}/include/msvc_compat/C99
+  if test "x${CPPFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CPPFLAGS="${CPPFLAGS}${T_APPEND_V}"
+else
+  CPPFLAGS="${CPPFLAGS} ${T_APPEND_V}"
+fi
+
+
 fi
 
 if test "x${je_cv_msvc}" = "xyes" ; then
   LG_SIZEOF_PTR=LG_SIZEOF_PTR_WIN
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using a predefined value for sizeof(void *): 4 for 32-bit, 8 for 64-bit" >&5
 $as_echo "Using a predefined value for sizeof(void *): 4 for 32-bit, 8 for 64-bit" >&6; }
 else
   # The cast to long int works around a bug in the HP C Compiler
@@ -5302,17 +5569,16 @@ ac_tool_warned=yes ;;
 esac
     AR=$ac_ct_AR
   fi
 else
   AR="$ac_cv_prog_AR"
 fi
 
 
-CFLAGS="$CFLAGS"
 default_munmap="1"
 maps_coalesce="1"
 case "${host}" in
   *-*-darwin* | *-*-ios*)
 	abi="macho"
 	RPATH=""
 	LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
 	so="dylib"
@@ -5334,31 +5600,45 @@ case "${host}" in
   *-*-openbsd*)
 	abi="elf"
 	force_tls="0"
 	;;
   *-*-bitrig*)
 	abi="elf"
 	;;
   *-*-linux-android)
-		CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+		T_APPEND_V=-D_GNU_SOURCE
+  if test "x${CPPFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CPPFLAGS="${CPPFLAGS}${T_APPEND_V}"
+else
+  CPPFLAGS="${CPPFLAGS} ${T_APPEND_V}"
+fi
+
+
 	abi="elf"
 	$as_echo "#define JEMALLOC_HAS_ALLOCA_H 1" >>confdefs.h
 
 	$as_echo "#define JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY  " >>confdefs.h
 
 	$as_echo "#define JEMALLOC_THREADED_INIT  " >>confdefs.h
 
 	$as_echo "#define JEMALLOC_C11ATOMICS 1" >>confdefs.h
 
 	force_tls="0"
 	default_munmap="0"
 	;;
   *-*-linux* | *-*-kfreebsd*)
-		CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+		T_APPEND_V=-D_GNU_SOURCE
+  if test "x${CPPFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CPPFLAGS="${CPPFLAGS}${T_APPEND_V}"
+else
+  CPPFLAGS="${CPPFLAGS} ${T_APPEND_V}"
+fi
+
+
 	abi="elf"
 	$as_echo "#define JEMALLOC_HAS_ALLOCA_H 1" >>confdefs.h
 
 	$as_echo "#define JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY  " >>confdefs.h
 
 	$as_echo "#define JEMALLOC_THREADED_INIT  " >>confdefs.h
 
 	$as_echo "#define JEMALLOC_USE_CXX_THROW  " >>confdefs.h
@@ -5391,18 +5671,32 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $abi" >&5
 $as_echo "$abi" >&6; }
 	;;
   *-*-solaris2*)
 	abi="elf"
 	RPATH='-Wl,-R,$(1)'
-		CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
-	LIBS="$LIBS -lposix4 -lsocket -lnsl"
+		T_APPEND_V=-D_POSIX_PTHREAD_SEMANTICS
+  if test "x${CPPFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CPPFLAGS="${CPPFLAGS}${T_APPEND_V}"
+else
+  CPPFLAGS="${CPPFLAGS} ${T_APPEND_V}"
+fi
+
+
+	T_APPEND_V=-lposix4 -lsocket -lnsl
+  if test "x${LIBS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  LIBS="${LIBS}${T_APPEND_V}"
+else
+  LIBS="${LIBS} ${T_APPEND_V}"
+fi
+
+
 	;;
   *-ibm-aix*)
 	if "$LG_SIZEOF_PTR" = "8"; then
 	  	  LD_PRELOAD_VAR="LDR_PRELOAD64"
 	else
 	  	  LD_PRELOAD_VAR="LDR_PRELOAD"
 	fi
 	abi="xcoff"
@@ -5604,123 +5898,169 @@ fi
 
 if test "x${je_cv_attribute}" = "xyes" ; then
   $as_echo "#define JEMALLOC_HAVE_ATTR  " >>confdefs.h
 
   if test "x${GCC}" = "xyes" -a "x${abi}" = "xelf"; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fvisibility=hidden" >&5
 $as_echo_n "checking whether compiler supports -fvisibility=hidden... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-fvisibility=hidden"
-else
-  CFLAGS="${CFLAGS} -fvisibility=hidden"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-fvisibility=hidden
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-fvisibility=hidden
+  je_cv_cflags_added=-fvisibility=hidden
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
   fi
 fi
-SAVED_CFLAGS="${CFLAGS}"
+SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror" >&5
 $as_echo_n "checking whether compiler supports -Werror... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Werror"
-else
-  CFLAGS="${CFLAGS} -Werror"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Werror
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Werror
+  je_cv_cflags_added=-Werror
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -herror_on_warning" >&5
 $as_echo_n "checking whether compiler supports -herror_on_warning... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-herror_on_warning"
-else
-  CFLAGS="${CFLAGS} -herror_on_warning"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-herror_on_warning
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-herror_on_warning
+  je_cv_cflags_added=-herror_on_warning
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether tls_model attribute is compilable" >&5
 $as_echo_n "checking whether tls_model attribute is compilable... " >&6; }
 if ${je_cv_tls_model+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5742,96 +6082,134 @@ else
   je_cv_tls_model=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_tls_model" >&5
 $as_echo "$je_cv_tls_model" >&6; }
 
-CFLAGS="${SAVED_CFLAGS}"
+CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}"
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
 if test "x${je_cv_tls_model}" = "xyes" ; then
   $as_echo "#define JEMALLOC_TLS_MODEL __attribute__((tls_model(\"initial-exec\")))" >>confdefs.h
 
 else
   $as_echo "#define JEMALLOC_TLS_MODEL  " >>confdefs.h
 
 fi
-SAVED_CFLAGS="${CFLAGS}"
+SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror" >&5
 $as_echo_n "checking whether compiler supports -Werror... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Werror"
-else
-  CFLAGS="${CFLAGS} -Werror"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Werror
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Werror
+  je_cv_cflags_added=-Werror
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -herror_on_warning" >&5
 $as_echo_n "checking whether compiler supports -herror_on_warning... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-herror_on_warning"
-else
-  CFLAGS="${CFLAGS} -herror_on_warning"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-herror_on_warning
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-herror_on_warning
+  je_cv_cflags_added=-herror_on_warning
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether alloc_size attribute is compilable" >&5
 $as_echo_n "checking whether alloc_size attribute is compilable... " >&6; }
 if ${je_cv_alloc_size+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5851,93 +6229,131 @@ else
   je_cv_alloc_size=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_alloc_size" >&5
 $as_echo "$je_cv_alloc_size" >&6; }
 
-CFLAGS="${SAVED_CFLAGS}"
+CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}"
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
 if test "x${je_cv_alloc_size}" = "xyes" ; then
   $as_echo "#define JEMALLOC_HAVE_ATTR_ALLOC_SIZE  " >>confdefs.h
 
 fi
-SAVED_CFLAGS="${CFLAGS}"
+SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror" >&5
 $as_echo_n "checking whether compiler supports -Werror... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Werror"
-else
-  CFLAGS="${CFLAGS} -Werror"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Werror
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Werror
+  je_cv_cflags_added=-Werror
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -herror_on_warning" >&5
 $as_echo_n "checking whether compiler supports -herror_on_warning... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-herror_on_warning"
-else
-  CFLAGS="${CFLAGS} -herror_on_warning"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-herror_on_warning
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-herror_on_warning
+  je_cv_cflags_added=-herror_on_warning
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether format(gnu_printf, ...) attribute is compilable" >&5
 $as_echo_n "checking whether format(gnu_printf, ...) attribute is compilable... " >&6; }
 if ${je_cv_format_gnu_printf+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -5957,93 +6373,131 @@ else
   je_cv_format_gnu_printf=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_format_gnu_printf" >&5
 $as_echo "$je_cv_format_gnu_printf" >&6; }
 
-CFLAGS="${SAVED_CFLAGS}"
+CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}"
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
 if test "x${je_cv_format_gnu_printf}" = "xyes" ; then
   $as_echo "#define JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF  " >>confdefs.h
 
 fi
-SAVED_CFLAGS="${CFLAGS}"
+SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror" >&5
 $as_echo_n "checking whether compiler supports -Werror... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Werror"
-else
-  CFLAGS="${CFLAGS} -Werror"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Werror
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Werror
+  je_cv_cflags_added=-Werror
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -herror_on_warning" >&5
 $as_echo_n "checking whether compiler supports -herror_on_warning... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-herror_on_warning"
-else
-  CFLAGS="${CFLAGS} -herror_on_warning"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-herror_on_warning
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-herror_on_warning
+  je_cv_cflags_added=-herror_on_warning
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether format(printf, ...) attribute is compilable" >&5
 $as_echo_n "checking whether format(printf, ...) attribute is compilable... " >&6; }
 if ${je_cv_format_printf+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -6063,17 +6517,24 @@ else
   je_cv_format_printf=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_format_printf" >&5
 $as_echo "$je_cv_format_printf" >&6; }
 
-CFLAGS="${SAVED_CFLAGS}"
+CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}"
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
 if test "x${je_cv_format_printf}" = "xyes" ; then
   $as_echo "#define JEMALLOC_HAVE_ATTR_FORMAT_PRINTF  " >>confdefs.h
 
 fi
 
 
 # Check whether --with-rpath was given.
 if test "${with_rpath+set}" = set; then :
@@ -6405,85 +6866,115 @@ fi
 
 if test "x$enable_code_coverage" = "x1" ; then
   deoptimize="no"
   echo "$CFLAGS $EXTRA_CFLAGS" | grep '\-O' >/dev/null || deoptimize="yes"
   if test "x${deoptimize}" = "xyes" ; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O0" >&5
 $as_echo_n "checking whether compiler supports -O0... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-O0"
-else
-  CFLAGS="${CFLAGS} -O0"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-O0
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-O0
+  je_cv_cflags_added=-O0
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
   fi
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fprofile-arcs -ftest-coverage" >&5
 $as_echo_n "checking whether compiler supports -fprofile-arcs -ftest-coverage... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-fprofile-arcs -ftest-coverage"
-else
-  CFLAGS="${CFLAGS} -fprofile-arcs -ftest-coverage"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-fprofile-arcs -ftest-coverage
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-fprofile-arcs -ftest-coverage
+  je_cv_cflags_added=-fprofile-arcs -ftest-coverage
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
   EXTRA_LDFLAGS="$EXTRA_LDFLAGS -fprofile-arcs -ftest-coverage"
   $as_echo "#define JEMALLOC_CODE_COVERAGE  " >>confdefs.h
 
 fi
 
 
 
@@ -6701,168 +7192,224 @@ else
 
 fi
 
 if test "x$enable_ivsalloc" = "x1" ; then
   $as_echo "#define JEMALLOC_IVSALLOC  " >>confdefs.h
 
 fi
 
-if test "x$enable_debug" = "x0" -a "x$no_CFLAGS" = "xyes" ; then
-    optimize="no"
-  echo "$CFLAGS $EXTRA_CFLAGS" | grep '\-O' >/dev/null || optimize="yes"
-  if test "x${optimize}" = "xyes" ; then
-    if test "x$GCC" = "xyes" ; then
+if test "x$enable_debug" = "x0" ; then
+  if test "x$GCC" = "xyes" ; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O3" >&5
 $as_echo_n "checking whether compiler supports -O3... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-O3"
-else
-  CFLAGS="${CFLAGS} -O3"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-O3
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-O3
+  je_cv_cflags_added=-O3
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -funroll-loops" >&5
 $as_echo_n "checking whether compiler supports -funroll-loops... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-funroll-loops"
-else
-  CFLAGS="${CFLAGS} -funroll-loops"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-funroll-loops
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-funroll-loops
+  je_cv_cflags_added=-funroll-loops
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-    elif test "x$je_cv_msvc" = "xyes" ; then
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
+  elif test "x$je_cv_msvc" = "xyes" ; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O2" >&5
 $as_echo_n "checking whether compiler supports -O2... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-O2"
-else
-  CFLAGS="${CFLAGS} -O2"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-O2
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-O2
+  je_cv_cflags_added=-O2
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-    else
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
+  else
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -O" >&5
 $as_echo_n "checking whether compiler supports -O... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-O"
-else
-  CFLAGS="${CFLAGS} -O"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-O
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-O
+  je_cv_cflags_added=-O
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-    fi
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
   fi
 fi
 
 # Check whether --enable-stats was given.
 if test "${enable_stats+set}" = set; then :
   enableval=$enable_stats; if test "x$enable_stats" = "xno" ; then
   enable_stats="0"
 else
@@ -6976,23 +7523,37 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unwind_unw_backtrace" >&5
 $as_echo "$ac_cv_lib_unwind_unw_backtrace" >&6; }
 if test "x$ac_cv_lib_unwind_unw_backtrace" = xyes; then :
-  LIBS="$LIBS $LUNWIND"
+  T_APPEND_V=$LUNWIND
+  if test "x${LIBS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  LIBS="${LIBS}${T_APPEND_V}"
+else
+  LIBS="${LIBS} ${T_APPEND_V}"
+fi
+
+
 else
   enable_prof_libunwind="0"
 fi
 
   else
-    LIBS="$LIBS $LUNWIND"
+    T_APPEND_V=$LUNWIND
+  if test "x${LIBS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  LIBS="${LIBS}${T_APPEND_V}"
+else
+  LIBS="${LIBS} ${T_APPEND_V}"
+fi
+
+
   fi
   if test "x${enable_prof_libunwind}" = "x1" ; then
     backtrace_method="libunwind"
     $as_echo "#define JEMALLOC_PROF_LIBUNWIND  " >>confdefs.h
 
   fi
 fi
 
@@ -7057,17 +7618,24 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcc__Unwind_Backtrace" >&5
 $as_echo "$ac_cv_lib_gcc__Unwind_Backtrace" >&6; }
 if test "x$ac_cv_lib_gcc__Unwind_Backtrace" = xyes; then :
-  LIBS="$LIBS -lgcc"
+  T_APPEND_V=-lgcc
+  if test "x${LIBS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  LIBS="${LIBS}${T_APPEND_V}"
+else
+  LIBS="${LIBS} ${T_APPEND_V}"
+fi
+
+
 else
   enable_prof_libgcc="0"
 fi
 
   if test "x${enable_prof_libgcc}" = "x1" ; then
     backtrace_method="libgcc"
     $as_echo "#define JEMALLOC_PROF_LIBGCC  " >>confdefs.h
 
@@ -7089,48 +7657,63 @@ else
 
 fi
 
 if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \
      -a "x$GCC" = "xyes" ; then
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -fno-omit-frame-pointer" >&5
 $as_echo_n "checking whether compiler supports -fno-omit-frame-pointer... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-fno-omit-frame-pointer"
-else
-  CFLAGS="${CFLAGS} -fno-omit-frame-pointer"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-fno-omit-frame-pointer
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-fno-omit-frame-pointer
+  je_cv_cflags_added=-fno-omit-frame-pointer
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
   backtrace_method="gcc intrinsics"
   $as_echo "#define JEMALLOC_PROF_GCC  " >>confdefs.h
 
 else
   enable_prof_gcc="0"
 fi
 
@@ -7138,19 +7721,24 @@ if test "x$backtrace_method" = "x" ; the
   backtrace_method="none (disabling profiling)"
   enable_prof="0"
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking configured backtracing method" >&5
 $as_echo_n "checking configured backtracing method... " >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $backtrace_method" >&5
 $as_echo "$backtrace_method" >&6; }
 if test "x$enable_prof" = "x1" ; then
-    if test "x$LM" != "x" ; then
-    LIBS="$LIBS $LM"
-  fi
+    T_APPEND_V=$LM
+  if test "x${LIBS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  LIBS="${LIBS}${T_APPEND_V}"
+else
+  LIBS="${LIBS} ${T_APPEND_V}"
+fi
+
+
 
   $as_echo "#define JEMALLOC_PROF  " >>confdefs.h
 
 fi
 
 
 # Check whether --enable-tcache was given.
 if test "${enable_tcache+set}" = set; then :
@@ -7764,17 +8352,24 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
 if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
-  LIBS="$LIBS -lpthread"
+  T_APPEND_V=-lpthread
+  if test "x${LIBS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  LIBS="${LIBS}${T_APPEND_V}"
+else
+  LIBS="${LIBS} ${T_APPEND_V}"
+fi
+
+
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_create" >&5
 $as_echo_n "checking for library containing pthread_create... " >&6; }
 if ${ac_cv_search_pthread_create+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7864,17 +8459,24 @@ fi
 $as_echo "$je_cv_pthread_atfork" >&6; }
 
   if test "x${je_cv_pthread_atfork}" = "xyes" ; then
     $as_echo "#define JEMALLOC_HAVE_PTHREAD_ATFORK  " >>confdefs.h
 
   fi
 fi
 
-CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+T_APPEND_V=-D_REENTRANT
+  if test "x${CPPFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CPPFLAGS="${CPPFLAGS}${T_APPEND_V}"
+else
+  CPPFLAGS="${CPPFLAGS} ${T_APPEND_V}"
+fi
+
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
 $as_echo_n "checking for library containing clock_gettime... " >&6; }
 if ${ac_cv_search_clock_gettime+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -7925,54 +8527,70 @@ ac_res=$ac_cv_search_clock_gettime
 if test "$ac_res" != no; then :
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
 fi
 
 
 if test "x$je_cv_cray_prgenv_wrapper" = "xyes" ; then
   if test "$ac_cv_search_clock_gettime" != "-lrt"; then
-    SAVED_CFLAGS="${CFLAGS}"
+    SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+
 
     unset ac_cv_search_clock_gettime
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -dynamic" >&5
 $as_echo_n "checking whether compiler supports -dynamic... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-dynamic"
-else
-  CFLAGS="${CFLAGS} -dynamic"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-dynamic
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-dynamic
+  je_cv_cflags_added=-dynamic
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5
 $as_echo_n "checking for library containing clock_gettime... " >&6; }
 if ${ac_cv_search_clock_gettime+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   ac_func_search_save_LIBS=$LIBS
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -8021,17 +8639,24 @@ fi
 $as_echo "$ac_cv_search_clock_gettime" >&6; }
 ac_res=$ac_cv_search_clock_gettime
 if test "$ac_res" != no; then :
   test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
 
 fi
 
 
-    CFLAGS="${SAVED_CFLAGS}"
+    CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}"
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
   fi
 fi
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is compilable" >&5
 $as_echo_n "checking whether clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is compilable... " >&6; }
 if ${je_cv_clock_monotonic_coarse+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -8158,52 +8783,68 @@ else
 fi
 
 else
   enable_syscall="1"
 
 fi
 
 if test "x$enable_syscall" = "x1" ; then
-      SAVED_CFLAGS="${CFLAGS}"
+      SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Werror" >&5
 $as_echo_n "checking whether compiler supports -Werror... " >&6; }
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="-Werror"
-else
-  CFLAGS="${CFLAGS} -Werror"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+T_APPEND_V=-Werror
+  if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}${T_APPEND_V}"
+else
+  CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS} ${T_APPEND_V}"
+fi
+
+
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 
 int
 main ()
 {
 
     return 0;
 
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  je_cv_cflags_appended=-Werror
+  je_cv_cflags_added=-Werror
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 else
-  je_cv_cflags_appended=
+  je_cv_cflags_added=
               { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-              CFLAGS="${TCFLAGS}"
+              CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"
 
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether syscall(2) is compilable" >&5
 $as_echo_n "checking whether syscall(2) is compilable... " >&6; }
 if ${je_cv_syscall+:} false; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -8228,17 +8869,24 @@ else
   je_cv_syscall=no
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_syscall" >&5
 $as_echo "$je_cv_syscall" >&6; }
 
-  CFLAGS="${SAVED_CFLAGS}"
+  CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}"
+if test "x${CONFIGURE_CFLAGS}" = "x" -o "x${SPECIFIED_CFLAGS}" = "x" ; then
+  CFLAGS="${CONFIGURE_CFLAGS}${SPECIFIED_CFLAGS}"
+else
+  CFLAGS="${CONFIGURE_CFLAGS} ${SPECIFIED_CFLAGS}"
+fi
+
+
   if test "x$je_cv_syscall" = "xyes" ; then
     $as_echo "#define JEMALLOC_USE_SYSCALL  " >>confdefs.h
 
   fi
 fi
 
 ac_fn_c_check_func "$LINENO" "secure_getenv" "ac_cv_func_secure_getenv"
 if test "x$ac_cv_func_secure_getenv" = xyes; then :
@@ -8372,17 +9020,24 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 LIBS=$ac_check_lib_save_LIBS
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5
 $as_echo "$ac_cv_lib_dl_dlsym" >&6; }
 if test "x$ac_cv_lib_dl_dlsym" = xyes; then :
-  LIBS="$LIBS -ldl"
+  T_APPEND_V=-ldl
+  if test "x${LIBS}" = "x" -o "x${T_APPEND_V}" = "x" ; then
+  LIBS="${LIBS}${T_APPEND_V}"
+else
+  LIBS="${LIBS} ${T_APPEND_V}"
+fi
+
+
 else
   as_fn_error $? "libdl is missing" "$LINENO" 5
 fi
 
 
 fi
 
   fi
@@ -8748,21 +9403,44 @@ else
 fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $je_cv_thp" >&5
 $as_echo "$je_cv_thp" >&6; }
 
   if test "x${je_cv_thp}" = "xyes" ; then
-    $as_echo "#define JEMALLOC_THP  " >>confdefs.h
+    $as_echo "#define JEMALLOC_HAVE_MADVISE_HUGE  " >>confdefs.h
 
   fi
 fi
 
+# Check whether --enable-thp was given.
+if test "${enable_thp+set}" = set; then :
+  enableval=$enable_thp; if test "x$enable_thp" = "xno" -o "x${je_cv_thp}" != "xyes" ; then
+  enable_thp="0"
+else
+  enable_thp="1"
+fi
+
+else
+  if test "x${je_cv_thp}" = "xyes" ; then
+  enable_thp="1"
+else
+  enable_thp="0"
+fi
+
+fi
+
+if test "x$enable_thp" = "x1" ; then
+  $as_echo "#define JEMALLOC_THP  " >>confdefs.h
+
+fi
+
+
 
 
 
 if test "x${je_cv_atomic9}" != "xyes" -a "x${je_cv_osatomic}" != "xyes" ; then
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to force 32-bit __sync_{add,sub}_and_fetch()" >&5
 $as_echo_n "checking whether to force 32-bit __sync_{add,sub}_and_fetch()... " >&6; }
 if ${je_cv_sync_compare_and_swap_4+:} false; then :
@@ -10688,18 +11366,20 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: library revision   : ${rev}" >&5
 $as_echo "library revision   : ${rev}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5
 $as_echo "" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: CONFIG             : ${CONFIG}" >&5
 $as_echo "CONFIG             : ${CONFIG}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: CC                 : ${CC}" >&5
 $as_echo "CC                 : ${CC}" >&6; }
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CFLAGS             : ${CFLAGS}" >&5
-$as_echo "CFLAGS             : ${CFLAGS}" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: CONFIGURE_CFLAGS   : ${CONFIGURE_CFLAGS}" >&5
+$as_echo "CONFIGURE_CFLAGS   : ${CONFIGURE_CFLAGS}" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: SPECIFIED_CFLAGS   : ${SPECIFIED_CFLAGS}" >&5
+$as_echo "SPECIFIED_CFLAGS   : ${SPECIFIED_CFLAGS}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: EXTRA_CFLAGS       : ${EXTRA_CFLAGS}" >&5
 $as_echo "EXTRA_CFLAGS       : ${EXTRA_CFLAGS}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: CPPFLAGS           : ${CPPFLAGS}" >&5
 $as_echo "CPPFLAGS           : ${CPPFLAGS}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: LDFLAGS            : ${LDFLAGS}" >&5
 $as_echo "LDFLAGS            : ${LDFLAGS}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}" >&5
 $as_echo "EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}" >&6; }
@@ -10764,16 +11444,18 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: prof-libunwind     : ${enable_prof_libunwind}" >&5
 $as_echo "prof-libunwind     : ${enable_prof_libunwind}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: prof-libgcc        : ${enable_prof_libgcc}" >&5
 $as_echo "prof-libgcc        : ${enable_prof_libgcc}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: prof-gcc           : ${enable_prof_gcc}" >&5
 $as_echo "prof-gcc           : ${enable_prof_gcc}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: tcache             : ${enable_tcache}" >&5
 $as_echo "tcache             : ${enable_tcache}" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: thp                : ${enable_thp}" >&5
+$as_echo "thp                : ${enable_thp}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: fill               : ${enable_fill}" >&5
 $as_echo "fill               : ${enable_fill}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: utrace             : ${enable_utrace}" >&5
 $as_echo "utrace             : ${enable_utrace}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: valgrind           : ${enable_valgrind}" >&5
 $as_echo "valgrind           : ${enable_valgrind}" >&6; }
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: xmalloc            : ${enable_xmalloc}" >&5
 $as_echo "xmalloc            : ${enable_xmalloc}" >&6; }
--- a/memory/jemalloc/src/configure.ac
+++ b/memory/jemalloc/src/configure.ac
@@ -1,39 +1,76 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT([Makefile.in])
 
 AC_CONFIG_AUX_DIR([build-aux])
 
 dnl ============================================================================
 dnl Custom macro definitions.
 
-dnl JE_CFLAGS_APPEND(cflag)
-AC_DEFUN([JE_CFLAGS_APPEND],
+dnl JE_CONCAT_VVV(r, a, b)
+dnl 
+dnl Set $r to the concatenation of $a and $b, with a space separating them iff
+dnl both $a and $b are non-emty.
+AC_DEFUN([JE_CONCAT_VVV],
+if test "x[$]{$2}" = "x" -o "x[$]{$3}" = "x" ; then
+  $1="[$]{$2}[$]{$3}"
+else
+  $1="[$]{$2} [$]{$3}"
+fi
+)
+
+dnl JE_APPEND_VS(a, b)
+dnl 
+dnl Set $a to the concatenation of $a and b, with a space separating them iff
+dnl both $a and b are non-empty.
+AC_DEFUN([JE_APPEND_VS],
+  T_APPEND_V=$2
+  JE_CONCAT_VVV($1, $1, T_APPEND_V)
+)
+
+CONFIGURE_CFLAGS=
+SPECIFIED_CFLAGS="${CFLAGS}"
+dnl JE_CFLAGS_ADD(cflag)
+dnl 
+dnl CFLAGS is the concatenation of CONFIGURE_CFLAGS and SPECIFIED_CFLAGS
+dnl (ignoring EXTRA_CFLAGS, which does not impact configure tests.  This macro
+dnl appends to CONFIGURE_CFLAGS and regenerates CFLAGS.
+AC_DEFUN([JE_CFLAGS_ADD],
 [
 AC_MSG_CHECKING([whether compiler supports $1])
-TCFLAGS="${CFLAGS}"
-if test "x${CFLAGS}" = "x" ; then
-  CFLAGS="$1"
-else
-  CFLAGS="${CFLAGS} $1"
-fi
+T_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+JE_APPEND_VS(CONFIGURE_CFLAGS, $1)
+JE_CONCAT_VVV(CFLAGS, CONFIGURE_CFLAGS, SPECIFIED_CFLAGS)
 AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
 [[
 ]], [[
     return 0;
 ]])],
-              [je_cv_cflags_appended=$1]
+              [je_cv_cflags_added=$1]
               AC_MSG_RESULT([yes]),
-              [je_cv_cflags_appended=]
+              [je_cv_cflags_added=]
               AC_MSG_RESULT([no])
-              [CFLAGS="${TCFLAGS}"]
+              [CONFIGURE_CFLAGS="${T_CONFIGURE_CFLAGS}"]
 )
+JE_CONCAT_VVV(CFLAGS, CONFIGURE_CFLAGS, SPECIFIED_CFLAGS)
 ])
 
+dnl JE_CFLAGS_SAVE()
+dnl JE_CFLAGS_RESTORE()
+dnl 
+dnl Save/restore CFLAGS.  Nesting is not supported.
+AC_DEFUN([JE_CFLAGS_SAVE],
+SAVED_CONFIGURE_CFLAGS="${CONFIGURE_CFLAGS}"
+)
+AC_DEFUN([JE_CFLAGS_RESTORE],
+CONFIGURE_CFLAGS="${SAVED_CONFIGURE_CFLAGS}"
+JE_CONCAT_VVV(CFLAGS, CONFIGURE_CFLAGS, SPECIFIED_CFLAGS)
+)
+
 dnl JE_COMPILABLE(label, hcode, mcode, rvar)
 dnl 
 dnl Use AC_LINK_IFELSE() rather than AC_COMPILE_IFELSE() so that linker errors
 dnl cause failure.
 AC_DEFUN([JE_COMPILABLE],
 [
 AC_CACHE_CHECK([whether $1 is compilable],
                [$4],
@@ -163,66 +200,65 @@ if test "x${je_cv_cray}" = "xyes" ; then
 #if !(_RELEASE_MAJOR == 8 && _RELEASE_MINOR == 4)
   int fail[-1];
 #endif
 ])],
                               [je_cv_cray_84=yes],
                               [je_cv_cray_84=no])])
 fi
 
-if test "x$CFLAGS" = "x" ; then
-  no_CFLAGS="yes"
-  if test "x$GCC" = "xyes" ; then
-    JE_CFLAGS_APPEND([-std=gnu11])
-    if test "x$je_cv_cflags_appended" = "x-std=gnu11" ; then
+if test "x$GCC" = "xyes" ; then
+  JE_CFLAGS_ADD([-std=gnu11])
+  if test "x$je_cv_cflags_added" = "x-std=gnu11" ; then
+    AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])
+  else
+    JE_CFLAGS_ADD([-std=gnu99])
+    if test "x$je_cv_cflags_added" = "x-std=gnu99" ; then
       AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])
-    else
-      JE_CFLAGS_APPEND([-std=gnu99])
-      if test "x$je_cv_cflags_appended" = "x-std=gnu99" ; then
-        AC_DEFINE_UNQUOTED([JEMALLOC_HAS_RESTRICT])
-      fi
-    fi
-    JE_CFLAGS_APPEND([-Wall])
-    JE_CFLAGS_APPEND([-Werror=declaration-after-statement])
-    JE_CFLAGS_APPEND([-Wshorten-64-to-32])
-    JE_CFLAGS_APPEND([-Wsign-compare])
-    JE_CFLAGS_APPEND([-pipe])
-    JE_CFLAGS_APPEND([-g3])
-  elif test "x$je_cv_msvc" = "xyes" ; then
-    CC="$CC -nologo"
-    JE_CFLAGS_APPEND([-Zi])
-    JE_CFLAGS_APPEND([-MT])
-    JE_CFLAGS_APPEND([-W3])
-    JE_CFLAGS_APPEND([-FS])
-    CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat"
-  fi
-  if test "x$je_cv_cray" = "xyes" ; then
-    dnl cray compiler 8.4 has an inlining bug
-    if test "x$je_cv_cray_84" = "xyes" ; then
-      JE_CFLAGS_APPEND([-hipa2])
-      JE_CFLAGS_APPEND([-hnognu])
-    fi
-    if test "x$enable_cc_silence" != "xno" ; then
-      dnl ignore unreachable code warning
-      JE_CFLAGS_APPEND([-hnomessage=128])
-      dnl ignore redefinition of "malloc", "free", etc warning
-      JE_CFLAGS_APPEND([-hnomessage=1357])
     fi
   fi
+  JE_CFLAGS_ADD([-Wall])
+  JE_CFLAGS_ADD([-Werror=declaration-after-statement])
+  JE_CFLAGS_ADD([-Wshorten-64-to-32])
+  JE_CFLAGS_ADD([-Wsign-compare])
+  JE_CFLAGS_ADD([-pipe])
+  JE_CFLAGS_ADD([-g3])
+elif test "x$je_cv_msvc" = "xyes" ; then
+  CC="$CC -nologo"
+  JE_CFLAGS_ADD([-Zi])
+  JE_CFLAGS_ADD([-MT])
+  JE_CFLAGS_ADD([-W3])
+  JE_CFLAGS_ADD([-FS])
+  JE_APPEND_VS(CPPFLAGS, -I${srcdir}/include/msvc_compat)
 fi
+if test "x$je_cv_cray" = "xyes" ; then
+  dnl cray compiler 8.4 has an inlining bug
+  if test "x$je_cv_cray_84" = "xyes" ; then
+    JE_CFLAGS_ADD([-hipa2])
+    JE_CFLAGS_ADD([-hnognu])
+  fi
+  if test "x$enable_cc_silence" != "xno" ; then
+    dnl ignore unreachable code warning
+    JE_CFLAGS_ADD([-hnomessage=128])
+    dnl ignore redefinition of "malloc", "free", etc warning
+    JE_CFLAGS_ADD([-hnomessage=1357])
+  fi
+fi
+AC_SUBST([CONFIGURE_CFLAGS])
+AC_SUBST([SPECIFIED_CFLAGS])
 AC_SUBST([EXTRA_CFLAGS])
 AC_PROG_CPP
 
 AC_C_BIGENDIAN([ac_cv_big_endian=1], [ac_cv_big_endian=0])
 if test "x${ac_cv_big_endian}" = "x1" ; then
   AC_DEFINE_UNQUOTED([JEMALLOC_BIG_ENDIAN], [ ])
 fi
 
 if test "x${je_cv_msvc}" = "xyes" -a "x${ac_cv_header_inttypes_h}" = "xno"; then
-  CPPFLAGS="$CPPFLAGS -I${srcdir}/include/msvc_compat/C99"
+  JE_APPEND_VS(CPPFLAGS, -I${srcdir}/include/msvc_compat/C99)
 fi
 
 if test "x${je_cv_msvc}" = "xyes" ; then
   LG_SIZEOF_PTR=LG_SIZEOF_PTR_WIN
   AC_MSG_RESULT([Using a predefined value for sizeof(void *): 4 for 32-bit, 8 for 64-bit])
 else
   AC_CHECK_SIZEOF([void *])
   if test "x${ac_cv_sizeof_void_p}" = "x8" ; then
@@ -343,17 +379,16 @@ AC_PROG_AR
 
 dnl Platform-specific settings.  abi and RPATH can probably be determined
 dnl programmatically, but doing so is error-prone, which makes it generally
 dnl not worth the trouble.
 dnl 
 dnl Define cpp macros in CPPFLAGS, rather than doing AC_DEFINE(macro), since the
 dnl definitions need to be seen before any headers are included, which is a pain
 dnl to make happen otherwise.
-CFLAGS="$CFLAGS"
 default_munmap="1"
 maps_coalesce="1"
 case "${host}" in
   *-*-darwin* | *-*-ios*)
 	abi="macho"
 	RPATH=""
 	LD_PRELOAD_VAR="DYLD_INSERT_LIBRARIES"
 	so="dylib"
@@ -375,28 +410,28 @@ case "${host}" in
 	abi="elf"
 	force_tls="0"
 	;;
   *-*-bitrig*)
 	abi="elf"
 	;;
   *-*-linux-android)
 	dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE.
-	CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+	JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE)
 	abi="elf"
 	AC_DEFINE([JEMALLOC_HAS_ALLOCA_H])
 	AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ])
 	AC_DEFINE([JEMALLOC_THREADED_INIT], [ ])
 	AC_DEFINE([JEMALLOC_C11ATOMICS])
 	force_tls="0"
 	default_munmap="0"
 	;;
   *-*-linux* | *-*-kfreebsd*)
 	dnl syscall(2) and secure_getenv(3) are exposed by _GNU_SOURCE.
-	CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
+	JE_APPEND_VS(CPPFLAGS, -D_GNU_SOURCE)
 	abi="elf"
 	AC_DEFINE([JEMALLOC_HAS_ALLOCA_H])
 	AC_DEFINE([JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY], [ ])
 	AC_DEFINE([JEMALLOC_THREADED_INIT], [ ])
 	AC_DEFINE([JEMALLOC_USE_CXX_THROW], [ ])
 	default_munmap="0"
 	;;
   *-*-netbsd*)
@@ -411,18 +446,18 @@ case "${host}" in
                           [abi="elf"],
                           [abi="aout"])
 	AC_MSG_RESULT([$abi])
 	;;
   *-*-solaris2*)
 	abi="elf"
 	RPATH='-Wl,-R,$(1)'
 	dnl Solaris needs this for sigwait().
-	CPPFLAGS="$CPPFLAGS -D_POSIX_PTHREAD_SEMANTICS"
-	LIBS="$LIBS -lposix4 -lsocket -lnsl"
+	JE_APPEND_VS(CPPFLAGS, -D_POSIX_PTHREAD_SEMANTICS)
+	JE_APPEND_VS(LIBS, -lposix4 -lsocket -lnsl)
 	;;
   *-ibm-aix*)
 	if "$LG_SIZEOF_PTR" = "8"; then
 	  dnl 64bit AIX
 	  LD_PRELOAD_VAR="LDR_PRELOAD64"
 	else
 	  dnl 32bit AIX
 	  LD_PRELOAD_VAR="LDR_PRELOAD"
@@ -510,65 +545,65 @@ AC_SUBST(LM)
 
 JE_COMPILABLE([__attribute__ syntax],
               [static __attribute__((unused)) void foo(void){}],
               [],
               [je_cv_attribute])
 if test "x${je_cv_attribute}" = "xyes" ; then
   AC_DEFINE([JEMALLOC_HAVE_ATTR], [ ])
   if test "x${GCC}" = "xyes" -a "x${abi}" = "xelf"; then
-    JE_CFLAGS_APPEND([-fvisibility=hidden])
+    JE_CFLAGS_ADD([-fvisibility=hidden])
   fi
 fi
 dnl Check for tls_model attribute support (clang 3.0 still lacks support).
-SAVED_CFLAGS="${CFLAGS}"
-JE_CFLAGS_APPEND([-Werror])
-JE_CFLAGS_APPEND([-herror_on_warning])
+JE_CFLAGS_SAVE()
+JE_CFLAGS_ADD([-Werror])
+JE_CFLAGS_ADD([-herror_on_warning])
 JE_COMPILABLE([tls_model attribute], [],
               [static __thread int
                __attribute__((tls_model("initial-exec"), unused)) foo;
                foo = 0;],
               [je_cv_tls_model])
-CFLAGS="${SAVED_CFLAGS}"
+JE_CFLAGS_RESTORE()
 if test "x${je_cv_tls_model}" = "xyes" ; then
   AC_DEFINE([JEMALLOC_TLS_MODEL],
             [__attribute__((tls_model("initial-exec")))])
 else
   AC_DEFINE([JEMALLOC_TLS_MODEL], [ ])
 fi
 dnl Check for alloc_size attribute support.
-SAVED_CFLAGS="${CFLAGS}"
-JE_CFLAGS_APPEND([-Werror])
-JE_CFLAGS_APPEND([-herror_on_warning])
+JE_CFLAGS_SAVE()
+JE_CFLAGS_ADD([-Werror])
+JE_CFLAGS_ADD([-herror_on_warning])
 JE_COMPILABLE([alloc_size attribute], [#include <stdlib.h>],
               [void *foo(size_t size) __attribute__((alloc_size(1)));],
               [je_cv_alloc_size])
-CFLAGS="${SAVED_CFLAGS}"
+JE_CFLAGS_RESTORE()
 if test "x${je_cv_alloc_size}" = "xyes" ; then
   AC_DEFINE([JEMALLOC_HAVE_ATTR_ALLOC_SIZE], [ ])
 fi
 dnl Check for format(gnu_printf, ...) attribute support.
-SAVED_CFLAGS="${CFLAGS}"
-JE_CFLAGS_APPEND([-Werror])
-JE_CFLAGS_APPEND([-herror_on_warning])
+JE_CFLAGS_SAVE()
+JE_CFLAGS_ADD([-Werror])
+JE_CFLAGS_ADD([-herror_on_warning])
 JE_COMPILABLE([format(gnu_printf, ...) attribute], [#include <stdlib.h>],
               [void *foo(const char *format, ...) __attribute__((format(gnu_printf, 1, 2)));],
               [je_cv_format_gnu_printf])
-CFLAGS="${SAVED_CFLAGS}"
+JE_CFLAGS_RESTORE()
 if test "x${je_cv_format_gnu_printf}" = "xyes" ; then
   AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_GNU_PRINTF], [ ])
 fi
 dnl Check for format(printf, ...) attribute support.
-SAVED_CFLAGS="${CFLAGS}"
-JE_CFLAGS_APPEND([-Werror])
-JE_CFLAGS_APPEND([-herror_on_warning])
+JE_CFLAGS_SAVE()
+JE_CFLAGS_ADD([-Werror])
+JE_CFLAGS_ADD([-herror_on_warning])
 JE_COMPILABLE([format(printf, ...) attribute], [#include <stdlib.h>],
               [void *foo(const char *format, ...) __attribute__((format(printf, 1, 2)));],
               [je_cv_format_printf])
-CFLAGS="${SAVED_CFLAGS}"
+JE_CFLAGS_RESTORE()
 if test "x${je_cv_format_printf}" = "xyes" ; then
   AC_DEFINE([JEMALLOC_HAVE_ATTR_FORMAT_PRINTF], [ ])
 fi
 
 dnl Support optional additions to rpath.
 AC_ARG_WITH([rpath],
   [AS_HELP_STRING([--with-rpath=<rpath>], [Colon-separated rpath (ELF systems only)])],
 if test "x$with_rpath" = "xno" ; then
@@ -620,19 +655,19 @@ else
 fi
 ],
 [enable_code_coverage="0"]
 )
 if test "x$enable_code_coverage" = "x1" ; then
   deoptimize="no"
   echo "$CFLAGS $EXTRA_CFLAGS" | grep '\-O' >/dev/null || deoptimize="yes"
   if test "x${deoptimize}" = "xyes" ; then
-    JE_CFLAGS_APPEND([-O0])
+    JE_CFLAGS_ADD([-O0])
   fi
-  JE_CFLAGS_APPEND([-fprofile-arcs -ftest-coverage])
+  JE_CFLAGS_ADD([-fprofile-arcs -ftest-coverage])
   EXTRA_LDFLAGS="$EXTRA_LDFLAGS -fprofile-arcs -ftest-coverage"
   AC_DEFINE([JEMALLOC_CODE_COVERAGE], [ ])
 fi
 AC_SUBST([enable_code_coverage])
 
 dnl Perform no name mangling by default.
 AC_ARG_WITH([mangling],
   [AS_HELP_STRING([--with-mangling=<map>], [Mangle symbols in <map>])],
@@ -812,29 +847,24 @@ fi
 ],
 [enable_ivsalloc="0"]
 )
 if test "x$enable_ivsalloc" = "x1" ; then
   AC_DEFINE([JEMALLOC_IVSALLOC], [ ])
 fi
 
 dnl Only optimize if not debugging.
-if test "x$enable_debug" = "x0" -a "x$no_CFLAGS" = "xyes" ; then
-  dnl Make sure that an optimization flag was not specified in EXTRA_CFLAGS.
-  optimize="no"
-  echo "$CFLAGS $EXTRA_CFLAGS" | grep '\-O' >/dev/null || optimize="yes"
-  if test "x${optimize}" = "xyes" ; then
-    if test "x$GCC" = "xyes" ; then
-      JE_CFLAGS_APPEND([-O3])
-      JE_CFLAGS_APPEND([-funroll-loops])
-    elif test "x$je_cv_msvc" = "xyes" ; then
-      JE_CFLAGS_APPEND([-O2])
-    else
-      JE_CFLAGS_APPEND([-O])
-    fi
+if test "x$enable_debug" = "x0" ; then
+  if test "x$GCC" = "xyes" ; then
+    JE_CFLAGS_ADD([-O3])
+    JE_CFLAGS_ADD([-funroll-loops])
+  elif test "x$je_cv_msvc" = "xyes" ; then
+    JE_CFLAGS_ADD([-O2])
+  else
+    JE_CFLAGS_ADD([-O])
   fi
 fi
 
 dnl Enable statistics calculation by default.
 AC_ARG_ENABLE([stats],
   [AS_HELP_STRING([--disable-stats],
                   [Disable statistics calculation/reporting])],
 [if test "x$enable_stats" = "xno" ; then
@@ -888,20 +918,20 @@ else
   fi
   LUNWIND="$with_static_libunwind"
 fi,
   LUNWIND="-lunwind"
 )
 if test "x$backtrace_method" = "x" -a "x$enable_prof_libunwind" = "x1" ; then
   AC_CHECK_HEADERS([libunwind.h], , [enable_prof_libunwind="0"])
   if test "x$LUNWIND" = "x-lunwind" ; then
-    AC_CHECK_LIB([unwind], [unw_backtrace], [LIBS="$LIBS $LUNWIND"],
+    AC_CHECK_LIB([unwind], [unw_backtrace], [JE_APPEND_VS(LIBS, $LUNWIND)],
                  [enable_prof_libunwind="0"])
   else
-    LIBS="$LIBS $LUNWIND"
+    JE_APPEND_VS(LIBS, $LUNWIND)
   fi
   if test "x${enable_prof_libunwind}" = "x1" ; then
     backtrace_method="libunwind"
     AC_DEFINE([JEMALLOC_PROF_LIBUNWIND], [ ])
   fi
 fi
 
 AC_ARG_ENABLE([prof-libgcc],
@@ -913,17 +943,17 @@ else
   enable_prof_libgcc="1"
 fi
 ],
 [enable_prof_libgcc="1"]
 )
 if test "x$backtrace_method" = "x" -a "x$enable_prof_libgcc" = "x1" \
      -a "x$GCC" = "xyes" ; then
   AC_CHECK_HEADERS([unwind.h], , [enable_prof_libgcc="0"])
-  AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [LIBS="$LIBS -lgcc"], [enable_prof_libgcc="0"])
+  AC_CHECK_LIB([gcc], [_Unwind_Backtrace], [JE_APPEND_VS(LIBS, -lgcc)], [enable_prof_libgcc="0"])
   if test "x${enable_prof_libgcc}" = "x1" ; then
     backtrace_method="libgcc"
     AC_DEFINE([JEMALLOC_PROF_LIBGCC], [ ])
   fi
 else
   enable_prof_libgcc="0"
 fi
 
@@ -935,34 +965,32 @@ AC_ARG_ENABLE([prof-gcc],
 else
   enable_prof_gcc="1"
 fi
 ],
 [enable_prof_gcc="1"]
 )
 if test "x$backtrace_method" = "x" -a "x$enable_prof_gcc" = "x1" \
      -a "x$GCC" = "xyes" ; then
-  JE_CFLAGS_APPEND([-fno-omit-frame-pointer])
+  JE_CFLAGS_ADD([-fno-omit-frame-pointer])
   backtrace_method="gcc intrinsics"
   AC_DEFINE([JEMALLOC_PROF_GCC], [ ])
 else
   enable_prof_gcc="0"
 fi
 
 if test "x$backtrace_method" = "x" ; then
   backtrace_method="none (disabling profiling)"
   enable_prof="0"
 fi
 AC_MSG_CHECKING([configured backtracing method])
 AC_MSG_RESULT([$backtrace_method])
 if test "x$enable_prof" = "x1" ; then
   dnl Heap profiling uses the log(3) function.
-  if test "x$LM" != "x" ; then
-    LIBS="$LIBS $LM"
-  fi
+  JE_APPEND_VS(LIBS, $LM)
 
   AC_DEFINE([JEMALLOC_PROF], [ ])
 fi
 AC_SUBST([enable_prof])
 
 dnl Enable thread-specific caching by default.
 AC_ARG_ENABLE([tcache],
   [AS_HELP_STRING([--disable-tcache], [Disable per thread caches])],
@@ -1321,45 +1349,45 @@ AC_SUBST([jemalloc_version_gid])
 
 dnl ============================================================================
 dnl Configure pthreads.
 
 if test "x$abi" != "xpecoff" ; then
   AC_CHECK_HEADERS([pthread.h], , [AC_MSG_ERROR([pthread.h is missing])])
   dnl Some systems may embed pthreads functionality in libc; check for libpthread
   dnl first, but try libc too before failing.
-  AC_CHECK_LIB([pthread], [pthread_create], [LIBS="$LIBS -lpthread"],
+  AC_CHECK_LIB([pthread], [pthread_create], [JE_APPEND_VS(LIBS, -lpthread)],
                [AC_SEARCH_LIBS([pthread_create], , ,
                                AC_MSG_ERROR([libpthread is missing]))])
   JE_COMPILABLE([pthread_atfork(3)], [
 #include <pthread.h>
 ], [
   pthread_atfork((void *)0, (void *)0, (void *)0);
 ], [je_cv_pthread_atfork])
   if test "x${je_cv_pthread_atfork}" = "xyes" ; then
     AC_DEFINE([JEMALLOC_HAVE_PTHREAD_ATFORK], [ ])
   fi
 fi
 
-CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+JE_APPEND_VS(CPPFLAGS, -D_REENTRANT)
 
 dnl Check whether clock_gettime(2) is in libc or librt.
 AC_SEARCH_LIBS([clock_gettime], [rt])
 
 dnl Cray wrapper compiler often adds `-lrt` when using `-static`. Check with
 dnl `-dynamic` as well in case a user tries to dynamically link in jemalloc
 if test "x$je_cv_cray_prgenv_wrapper" = "xyes" ; then
   if test "$ac_cv_search_clock_gettime" != "-lrt"; then
-    SAVED_CFLAGS="${CFLAGS}"
+    JE_CFLAGS_SAVE()
 
     unset ac_cv_search_clock_gettime
-    JE_CFLAGS_APPEND([-dynamic])
+    JE_CFLAGS_ADD([-dynamic])
     AC_SEARCH_LIBS([clock_gettime], [rt])
 
-    CFLAGS="${SAVED_CFLAGS}"
+    JE_CFLAGS_RESTORE()
   fi
 fi
 
 dnl check for CLOCK_MONOTONIC_COARSE (Linux-specific).
 JE_COMPILABLE([clock_gettime(CLOCK_MONOTONIC_COARSE, ...)], [
 #include <time.h>
 ], [
 	struct timespec ts;
@@ -1405,26 +1433,26 @@ else
   enable_syscall="1"
 fi
 ],
 [enable_syscall="1"]
 )
 if test "x$enable_syscall" = "x1" ; then
   dnl Check if syscall(2) is usable.  Treat warnings as errors, so that e.g. OS
   dnl X 10.12's deprecation warning prevents use.
-  SAVED_CFLAGS="${CFLAGS}"
-  JE_CFLAGS_APPEND([-Werror])
+  JE_CFLAGS_SAVE()
+  JE_CFLAGS_ADD([-Werror])
   JE_COMPILABLE([syscall(2)], [
 #include <sys/syscall.h>
 #include <unistd.h>
 ], [
 	syscall(SYS_write, 2, "hello", 5);
 ],
                 [je_cv_syscall])
-  CFLAGS="${SAVED_CFLAGS}"
+  JE_CFLAGS_RESTORE()
   if test "x$je_cv_syscall" = "xyes" ; then
     AC_DEFINE([JEMALLOC_USE_SYSCALL], [ ])
   fi
 fi
 
 dnl Check if the GNU-specific secure_getenv function exists.
 AC_CHECK_FUNC([secure_getenv],
               [have_secure_getenv="1"],
@@ -1490,17 +1518,17 @@ fi
 if test "x${enable_lazy_lock}" = "x1" -a "x${abi}" = "xpecoff" ; then
   AC_MSG_RESULT([Forcing no lazy-lock because thread creation monitoring is unimplemented])
   enable_lazy_lock="0"
 fi
 if test "x$enable_lazy_lock" = "x1" ; then
   if test "x$abi" != "xpecoff" ; then
     AC_CHECK_HEADERS([dlfcn.h], , [AC_MSG_ERROR([dlfcn.h is missing])])
     AC_CHECK_FUNC([dlsym], [],
-      [AC_CHECK_LIB([dl], [dlsym], [LIBS="$LIBS -ldl"],
+      [AC_CHECK_LIB([dl], [dlsym], [JE_APPEND_VS(LIBS, -ldl)],
                     [AC_MSG_ERROR([libdl is missing])])
       ])
   fi
   AC_DEFINE([JEMALLOC_LAZY_LOCK], [ ])
 fi
 AC_SUBST([enable_lazy_lock])
 
 AC_ARG_ENABLE([tls],
@@ -1650,20 +1678,41 @@ if test "x${je_cv_madvise}" = "xyes" ; t
   dnl Check for madvise(..., MADV_[NO]HUGEPAGE).
   JE_COMPILABLE([madvise(..., MADV_[[NO]]HUGEPAGE)], [
 #include <sys/mman.h>
 ], [
 	madvise((void *)0, 0, MADV_HUGEPAGE);
 	madvise((void *)0, 0, MADV_NOHUGEPAGE);
 ], [je_cv_thp])
   if test "x${je_cv_thp}" = "xyes" ; then
-    AC_DEFINE([JEMALLOC_THP], [ ])
+    AC_DEFINE([JEMALLOC_HAVE_MADVISE_HUGE], [ ])
   fi
 fi
 
+dnl Enable transparent huge page support by default.
+AC_ARG_ENABLE([thp],
+  [AS_HELP_STRING([--disable-thp],
+                  [Disable transparent huge page supprot])],
+[if test "x$enable_thp" = "xno" -o "x${je_cv_thp}" != "xyes" ; then
+  enable_thp="0"
+else
+  enable_thp="1"
+fi
+],
+[if test "x${je_cv_thp}" = "xyes" ; then
+  enable_thp="1"
+else
+  enable_thp="0"
+fi
+])
+if test "x$enable_thp" = "x1" ; then
+  AC_DEFINE([JEMALLOC_THP], [ ])
+fi
+AC_SUBST([enable_thp])
+
 dnl ============================================================================
 dnl Check whether __sync_{add,sub}_and_fetch() are available despite
 dnl __GCC_HAVE_SYNC_COMPARE_AND_SWAP_n macros being undefined.
 
 AC_DEFUN([JE_SYNC_COMPARE_AND_SWAP_CHECK],[
   AC_CACHE_CHECK([whether to force $1-bit __sync_{add,sub}_and_fetch()],
                [je_cv_sync_compare_and_swap_$2],
                [AC_LINK_IFELSE([AC_LANG_PROGRAM([
@@ -1942,17 +1991,18 @@ AC_OUTPUT
 dnl ============================================================================
 dnl Print out the results of configuration.
 AC_MSG_RESULT([===============================================================================])
 AC_MSG_RESULT([jemalloc version   : ${jemalloc_version}])
 AC_MSG_RESULT([library revision   : ${rev}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([CONFIG             : ${CONFIG}])
 AC_MSG_RESULT([CC                 : ${CC}])
-AC_MSG_RESULT([CFLAGS             : ${CFLAGS}])
+AC_MSG_RESULT([CONFIGURE_CFLAGS   : ${CONFIGURE_CFLAGS}])
+AC_MSG_RESULT([SPECIFIED_CFLAGS   : ${SPECIFIED_CFLAGS}])
 AC_MSG_RESULT([EXTRA_CFLAGS       : ${EXTRA_CFLAGS}])
 AC_MSG_RESULT([CPPFLAGS           : ${CPPFLAGS}])
 AC_MSG_RESULT([LDFLAGS            : ${LDFLAGS}])
 AC_MSG_RESULT([EXTRA_LDFLAGS      : ${EXTRA_LDFLAGS}])
 AC_MSG_RESULT([LIBS               : ${LIBS}])
 AC_MSG_RESULT([RPATH_EXTRA        : ${RPATH_EXTRA}])
 AC_MSG_RESULT([])
 AC_MSG_RESULT([XSLTPROC           : ${XSLTPROC}])
@@ -1980,16 +2030,17 @@ AC_MSG_RESULT([cc-silence         : ${en
 AC_MSG_RESULT([debug              : ${enable_debug}])
 AC_MSG_RESULT([code-coverage      : ${enable_code_coverage}])
 AC_MSG_RESULT([stats              : ${enable_stats}])
 AC_MSG_RESULT([prof               : ${enable_prof}])
 AC_MSG_RESULT([prof-libunwind     : ${enable_prof_libunwind}])
 AC_MSG_RESULT([prof-libgcc        : ${enable_prof_libgcc}])
 AC_MSG_RESULT([prof-gcc           : ${enable_prof_gcc}])
 AC_MSG_RESULT([tcache             : ${enable_tcache}])
+AC_MSG_RESULT([thp                : ${enable_thp}])
 AC_MSG_RESULT([fill               : ${enable_fill}])
 AC_MSG_RESULT([utrace             : ${enable_utrace}])
 AC_MSG_RESULT([valgrind           : ${enable_valgrind}])
 AC_MSG_RESULT([xmalloc            : ${enable_xmalloc}])
 AC_MSG_RESULT([munmap             : ${enable_munmap}])
 AC_MSG_RESULT([lazy_lock          : ${enable_lazy_lock}])
 AC_MSG_RESULT([tls                : ${enable_tls}])
 AC_MSG_RESULT([cache-oblivious    : ${enable_cache_oblivious}])
--- a/memory/jemalloc/src/doc/jemalloc.xml.in
+++ b/memory/jemalloc/src/doc/jemalloc.xml.in
@@ -845,16 +845,27 @@ for (i = 0; i < nbins; i++) {
           <mallctl>config.tcache</mallctl>
           (<type>bool</type>)
           <literal>r-</literal>
         </term>
         <listitem><para><option>--disable-tcache</option> was not specified
         during build configuration.</para></listitem>
       </varlistentry>
 
+      <varlistentry id="config.thp">
+        <term>
+          <mallctl>config.thp</mallctl>
+          (<type>bool</type>)
+          <literal>r-</literal>
+        </term>
+        <listitem><para><option>--disable-thp</option> was not specified
+        during build configuration, and the system supports transparent huge
+        page manipulation.</para></listitem>
+      </varlistentry>
+
       <varlistentry id="config.tls">
         <term>
           <mallctl>config.tls</mallctl>
           (<type>bool</type>)
           <literal>r-</literal>
         </term>
         <listitem><para><option>--disable-tls</option> was not specified during
         build configuration.</para></listitem>
@@ -1157,16 +1168,31 @@ malloc_conf = "xmalloc:true";]]></progra
         increased memory use.  See the <link
         linkend="opt.lg_tcache_max"><mallctl>opt.lg_tcache_max</mallctl></link>
         option for related tuning information.  This option is enabled by
         default unless running inside <ulink
         url="http://valgrind.org/">Valgrind</ulink>, in which case it is
         forcefully disabled.</para></listitem>
       </varlistentry>
 
+      <varlistentry id="opt.thp">
+        <term>
+          <mallctl>opt.thp</mallctl>
+          (<type>bool</type>)
+          <literal>r-</literal>
+          [<option>--enable-thp</option>]
+        </term>
+        <listitem><para>Transparent huge page (THP) integration
+        enabled/disabled.  When enabled, THPs are explicitly disabled as a side
+        effect of unused dirty page purging for chunks that back small and/or
+        large allocations, because such chunks typically comprise active,
+        unused dirty, and untouched clean pages.  This option is enabled by
+        default.</para></listitem>
+      </varlistentry>
+
       <varlistentry id="opt.lg_tcache_max">
         <term>
           <mallctl>opt.lg_tcache_max</mallctl>
           (<type>size_t</type>)
           <literal>r-</literal>
           [<option>--enable-tcache</option>]
         </term>
         <listitem><para>Maximum size class (log base 2) to cache in the
--- a/memory/jemalloc/src/include/jemalloc/internal/arena.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/arena.h
@@ -501,16 +501,17 @@ struct arena_tdata_s {
 static const size_t	large_pad =
 #ifdef JEMALLOC_CACHE_OBLIVIOUS
     PAGE
 #else
     0
 #endif
     ;
 
+extern bool		opt_thp;
 extern purge_mode_t	opt_purge;
 extern const char	*purge_mode_names[];
 extern ssize_t		opt_lg_dirty_mult;
 extern ssize_t		opt_decay_time;
 
 extern arena_bin_info_t	arena_bin_info[NBINS];
 
 extern size_t		map_bias; /* Number of arena chunk header pages. */
--- a/memory/jemalloc/src/include/jemalloc/internal/chunk.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/chunk.h
@@ -47,18 +47,18 @@ extern size_t		chunksize_mask; /* (chunk
 extern size_t		chunk_npages;
 
 extern const chunk_hooks_t	chunk_hooks_default;
 
 chunk_hooks_t	chunk_hooks_get(tsdn_t *tsdn, arena_t *arena);
 chunk_hooks_t	chunk_hooks_set(tsdn_t *tsdn, arena_t *arena,
     const chunk_hooks_t *chunk_hooks);
 
-bool	chunk_register(tsdn_t *tsdn, const void *chunk,
-    const extent_node_t *node);
+bool	chunk_register(const void *chunk, const extent_node_t *node,
+    bool *gdump);
 void	chunk_deregister(const void *chunk, const extent_node_t *node);
 void	*chunk_alloc_base(size_t size);
 void	*chunk_alloc_cache(tsdn_t *tsdn, arena_t *arena,
     chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
     size_t *sn, bool *zero, bool *commit, bool dalloc_node);
 void	*chunk_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
     chunk_hooks_t *chunk_hooks, void *new_addr, size_t size, size_t alignment,
     size_t *sn, bool *zero, bool *commit);
--- a/memory/jemalloc/src/include/jemalloc/internal/extent.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/extent.h
@@ -70,16 +70,21 @@ struct extent_node_s {
 	rb_node(extent_node_t)	ad_link;
 };
 typedef rb_tree(extent_node_t) extent_tree_t;
 
 #endif /* JEMALLOC_H_STRUCTS */
 /******************************************************************************/
 #ifdef JEMALLOC_H_EXTERNS
 
+#ifdef JEMALLOC_JET
+size_t	extent_size_quantize_floor(size_t size);
+#endif
+size_t	extent_size_quantize_ceil(size_t size);
+
 rb_proto(, extent_tree_szsnad_, extent_tree_t, extent_node_t)
 
 rb_proto(, extent_tree_ad_, extent_tree_t, extent_node_t)
 
 #endif /* JEMALLOC_H_EXTERNS */
 /******************************************************************************/
 #ifdef JEMALLOC_H_INLINES
 
--- a/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal.h.in
+++ b/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal.h.in
@@ -94,16 +94,23 @@ static const bool config_stats =
     ;
 static const bool config_tcache =
 #ifdef JEMALLOC_TCACHE
     true
 #else
     false
 #endif
     ;
+static const bool config_thp =
+#ifdef JEMALLOC_THP
+    true
+#else
+    false
+#endif
+    ;
 static const bool config_tls =
 #ifdef JEMALLOC_TLS
     true
 #else
     false
 #endif
     ;
 static const bool config_utrace =
--- a/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal_defs.h.in
+++ b/memory/jemalloc/src/include/jemalloc/internal/jemalloc_internal_defs.h.in
@@ -248,31 +248,34 @@
  */
 #undef JEMALLOC_SYSCTL_VM_OVERCOMMIT
 #undef JEMALLOC_PROC_SYS_VM_OVERCOMMIT_MEMORY
 
 /* Defined if madvise(2) is available. */
 #undef JEMALLOC_HAVE_MADVISE
 
 /*
+ * Defined if transparent huge pages are supported via the MADV_[NO]HUGEPAGE
+ * arguments to madvise(2).
+ */
+#undef JEMALLOC_HAVE_MADVISE_HUGE
+
+/*
  * Methods for purging unused pages differ between operating systems.
  *
  *   madvise(..., MADV_FREE) : This marks pages as being unused, such that they
  *                             will be discarded rather than swapped out.
  *   madvise(..., MADV_DONTNEED) : This immediately discards pages, such that
  *                                 new pages will be demand-zeroed if the
  *                                 address region is later touched.
  */
 #undef JEMALLOC_PURGE_MADVISE_FREE
 #undef JEMALLOC_PURGE_MADVISE_DONTNEED
 
-/*
- * Defined if transparent huge pages are supported via the MADV_[NO]HUGEPAGE
- * arguments to madvise(2).
- */
+/* Defined if transparent huge page support is enabled. */
 #undef JEMALLOC_THP
 
 /* Define if operating system has alloca.h header. */
 #undef JEMALLOC_HAS_ALLOCA_H
 
 /* C99 restrict keyword supported. */
 #undef JEMALLOC_HAS_RESTRICT
 
--- a/memory/jemalloc/src/include/jemalloc/internal/mutex.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/mutex.h
@@ -80,41 +80,41 @@ void	malloc_mutex_assert_owner(tsdn_t *t
 void	malloc_mutex_assert_not_owner(tsdn_t *tsdn, malloc_mutex_t *mutex);
 #endif
 
 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
 JEMALLOC_INLINE void
 malloc_mutex_lock(tsdn_t *tsdn, malloc_mutex_t *mutex)
 {
 
+	witness_assert_not_owner(tsdn, &mutex->witness);
 	if (isthreaded) {
-		witness_assert_not_owner(tsdn, &mutex->witness);
 #ifdef _WIN32
 #  if _WIN32_WINNT >= 0x0600
 		AcquireSRWLockExclusive(&mutex->lock);
 #  else
 		EnterCriticalSection(&mutex->lock);
 #  endif
 #elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
 		os_unfair_lock_lock(&mutex->lock);
 #elif (defined(JEMALLOC_OSSPIN))
 		OSSpinLockLock(&mutex->lock);
 #else
 		pthread_mutex_lock(&mutex->lock);
 #endif
-		witness_lock(tsdn, &mutex->witness);
 	}
+	witness_lock(tsdn, &mutex->witness);
 }
 
 JEMALLOC_INLINE void
 malloc_mutex_unlock(tsdn_t *tsdn, malloc_mutex_t *mutex)
 {
 
+	witness_unlock(tsdn, &mutex->witness);
 	if (isthreaded) {
-		witness_unlock(tsdn, &mutex->witness);
 #ifdef _WIN32
 #  if _WIN32_WINNT >= 0x0600
 		ReleaseSRWLockExclusive(&mutex->lock);
 #  else
 		LeaveCriticalSection(&mutex->lock);
 #  endif
 #elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
 		os_unfair_lock_unlock(&mutex->lock);
@@ -125,23 +125,21 @@ malloc_mutex_unlock(tsdn_t *tsdn, malloc
 #endif
 	}
 }
 
 JEMALLOC_INLINE void
 malloc_mutex_assert_owner(tsdn_t *tsdn, malloc_mutex_t *mutex)
 {
 
-	if (isthreaded)
-		witness_assert_owner(tsdn, &mutex->witness);
+	witness_assert_owner(tsdn, &mutex->witness);
 }
 
 JEMALLOC_INLINE void
 malloc_mutex_assert_not_owner(tsdn_t *tsdn, malloc_mutex_t *mutex)
 {
 
-	if (isthreaded)
-		witness_assert_not_owner(tsdn, &mutex->witness);
+	witness_assert_not_owner(tsdn, &mutex->witness);
 }
 #endif
 
 #endif /* JEMALLOC_H_INLINES */
 /******************************************************************************/
--- a/memory/jemalloc/src/include/jemalloc/internal/private_symbols.txt
+++ b/memory/jemalloc/src/include/jemalloc/internal/private_symbols.txt
@@ -218,16 +218,18 @@ extent_node_init
 extent_node_prof_tctx_get
 extent_node_prof_tctx_set
 extent_node_size_get
 extent_node_size_set
 extent_node_sn_get
 extent_node_sn_set
 extent_node_zeroed_get
 extent_node_zeroed_set
+extent_size_quantize_ceil
+extent_size_quantize_floor
 extent_tree_ad_destroy
 extent_tree_ad_destroy_recurse
 extent_tree_ad_empty
 extent_tree_ad_first
 extent_tree_ad_insert
 extent_tree_ad_iter
 extent_tree_ad_iter_recurse
 extent_tree_ad_iter_start
@@ -385,16 +387,17 @@ opt_prof_gdump
 opt_prof_leak
 opt_prof_prefix
 opt_prof_thread_active_init
 opt_purge
 opt_quarantine
 opt_redzone
 opt_stats_print
 opt_tcache
+opt_thp
 opt_utrace
 opt_xmalloc
 opt_zero
 p2rz
 pages_boot
 pages_commit
 pages_decommit
 pages_huge
@@ -524,16 +527,19 @@ tcache_enabled_cleanup
 tcache_enabled_get
 tcache_enabled_set
 tcache_event
 tcache_event_hard
 tcache_flush
 tcache_get
 tcache_get_hard
 tcache_maxclass
+tcache_postfork_child
+tcache_postfork_parent
+tcache_prefork
 tcache_salloc
 tcache_stats_merge
 tcaches
 tcaches_create
 tcaches_destroy
 tcaches_flush
 tcaches_get
 thread_allocated_cleanup
@@ -607,24 +613,26 @@ tsd_witnessesp_get
 tsdn_fetch
 tsdn_null
 tsdn_tsd
 u2rz
 valgrind_freelike_block
 valgrind_make_mem_defined
 valgrind_make_mem_noaccess
 valgrind_make_mem_undefined
+witness_assert_depth
+witness_assert_depth_to_rank
 witness_assert_lockless
 witness_assert_not_owner
 witness_assert_owner
+witness_depth_error
 witness_fork_cleanup
 witness_init
 witness_lock
 witness_lock_error
-witness_lockless_error
 witness_not_owner_error
 witness_owner
 witness_owner_error
 witness_postfork_child
 witness_postfork_parent
 witness_prefork
 witness_unlock
 witnesses_cleanup
--- a/memory/jemalloc/src/include/jemalloc/internal/tcache.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/tcache.h
@@ -144,16 +144,19 @@ tcache_t *tcache_get_hard(tsd_t *tsd);
 tcache_t *tcache_create(tsdn_t *tsdn, arena_t *arena);
 void	tcache_cleanup(tsd_t *tsd);
 void	tcache_enabled_cleanup(tsd_t *tsd);
 void	tcache_stats_merge(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena);
 bool	tcaches_create(tsd_t *tsd, unsigned *r_ind);
 void	tcaches_flush(tsd_t *tsd, unsigned ind);
 void	tcaches_destroy(tsd_t *tsd, unsigned ind);
 bool	tcache_boot(tsdn_t *tsdn);
+void tcache_prefork(tsdn_t *tsdn);
+void tcache_postfork_parent(tsdn_t *tsdn);
+void tcache_postfork_child(tsdn_t *tsdn);
 
 #endif /* JEMALLOC_H_EXTERNS */
 /******************************************************************************/
 #ifdef JEMALLOC_H_INLINES
 
 #ifndef JEMALLOC_ENABLE_INLINE
 void	tcache_event(tsd_t *tsd, tcache_t *tcache);
 void	tcache_flush(void);
--- a/memory/jemalloc/src/include/jemalloc/internal/tsd.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/tsd.h
@@ -474,23 +474,24 @@ a_name##tsd_wrapper_set(a_name##tsd_wrap
 a_attr a_name##tsd_wrapper_t *						\
 a_name##tsd_wrapper_get(bool init)					\
 {									\
 	a_name##tsd_wrapper_t *wrapper = (a_name##tsd_wrapper_t *)	\
 	    pthread_getspecific(a_name##tsd_tsd);			\
 									\
 	if (init && unlikely(wrapper == NULL)) {			\
 		tsd_init_block_t block;					\
-		wrapper = tsd_init_check_recursion(			\
-		    &a_name##tsd_init_head, &block);			\
+		wrapper = (a_name##tsd_wrapper_t *)			\
+		    tsd_init_check_recursion(&a_name##tsd_init_head,	\
+		    &block);						\
 		if (wrapper)						\
 		    return (wrapper);					\
 		wrapper = (a_name##tsd_wrapper_t *)			\
 		    malloc_tsd_malloc(sizeof(a_name##tsd_wrapper_t));	\
-		block.data = wrapper;					\
+		block.data = (void *)wrapper;				\
 		if (wrapper == NULL) {					\
 			malloc_write("<jemalloc>: Error allocating"	\
 			    " TSD for "#a_name"\n");			\
 			abort();					\
 		} else {						\
 			wrapper->initialized = false;			\
 			wrapper->val = a_initializer;			\
 		}							\
--- a/memory/jemalloc/src/include/jemalloc/internal/witness.h
+++ b/memory/jemalloc/src/include/jemalloc/internal/witness.h
@@ -7,31 +7,42 @@ typedef ql_head(witness_t) witness_list_
 typedef int witness_comp_t (const witness_t *, const witness_t *);
 
 /*
  * Lock ranks.  Witnesses with rank WITNESS_RANK_OMIT are completely ignored by
  * the witness machinery.
  */
 #define	WITNESS_RANK_OMIT		0U
 
+#define WITNESS_RANK_MIN		1U
+
 #define	WITNESS_RANK_INIT		1U
 #define	WITNESS_RANK_CTL		1U
-#define	WITNESS_RANK_ARENAS		2U
+#define WITNESS_RANK_TCACHES		2U
+#define	WITNESS_RANK_ARENAS		3U
+
+#define	WITNESS_RANK_PROF_DUMP		4U
+#define	WITNESS_RANK_PROF_BT2GCTX	5U
+#define	WITNESS_RANK_PROF_TDATAS	6U
+#define	WITNESS_RANK_PROF_TDATA		7U
+#define	WITNESS_RANK_PROF_GCTX		8U
 
-#define	WITNESS_RANK_PROF_DUMP		3U
-#define	WITNESS_RANK_PROF_BT2GCTX	4U
-#define	WITNESS_RANK_PROF_TDATAS	5U
-#define	WITNESS_RANK_PROF_TDATA		6U
-#define	WITNESS_RANK_PROF_GCTX		7U
+/*
+ * Used as an argument to witness_assert_depth_to_rank() in order to validate
+ * depth excluding non-core locks with lower ranks.  Since the rank argument to
+ * witness_assert_depth_to_rank() is inclusive rather than exclusive, this
+ * definition can have the same value as the minimally ranked core lock.
+ */
+#define WITNESS_RANK_CORE		9U
 
-#define	WITNESS_RANK_ARENA		8U
-#define	WITNESS_RANK_ARENA_CHUNKS	9U
-#define	WITNESS_RANK_ARENA_NODE_CACHE	10
+#define	WITNESS_RANK_ARENA		9U
+#define	WITNESS_RANK_ARENA_CHUNKS	10U
+#define	WITNESS_RANK_ARENA_NODE_CACHE	11U
 
-#define	WITNESS_RANK_BASE		11U
+#define	WITNESS_RANK_BASE		12U
 
 #define	WITNESS_RANK_LEAF		0xffffffffU
 #define	WITNESS_RANK_ARENA_BIN		WITNESS_RANK_LEAF
 #define	WITNESS_RANK_ARENA_HUGE		WITNESS_RANK_LEAF
 #define	WITNESS_RANK_DSS		WITNESS_RANK_LEAF
 #define	WITNESS_RANK_PROF_ACTIVE	WITNESS_RANK_LEAF
 #define	WITNESS_RANK_PROF_DUMP_SEQ	WITNESS_RANK_LEAF
 #define	WITNESS_RANK_PROF_GDUMP		WITNESS_RANK_LEAF
@@ -86,48 +97,55 @@ void	witness_owner_error(const witness_t
 #endif
 #ifdef JEMALLOC_JET
 typedef void (witness_not_owner_error_t)(const witness_t *);
 extern witness_not_owner_error_t *witness_not_owner_error;
 #else
 void	witness_not_owner_error(const witness_t *witness);
 #endif
 #ifdef JEMALLOC_JET
-typedef void (witness_lockless_error_t)(const witness_list_t *);
-extern witness_lockless_error_t *witness_lockless_error;
+typedef void (witness_depth_error_t)(const witness_list_t *,
+    witness_rank_t rank_inclusive, unsigned depth);
+extern witness_depth_error_t *witness_depth_error;
 #else
-void	witness_lockless_error(const witness_list_t *witnesses);
+void	witness_depth_error(const witness_list_t *witnesses,
+    witness_rank_t rank_inclusive, unsigned depth);
 #endif
 
 void	witnesses_cleanup(tsd_t *tsd);
 void	witness_fork_cleanup(tsd_t *tsd);
 void	witness_prefork(tsd_t *tsd);
 void	witness_postfork_parent(tsd_t *tsd);
 void	witness_postfork_child(tsd_t *tsd);
 
 #endif /* JEMALLOC_H_EXTERNS */
 /******************************************************************************/
 #ifdef JEMALLOC_H_INLINES
 
 #ifndef JEMALLOC_ENABLE_INLINE
 bool	witness_owner(tsd_t *tsd, const witness_t *witness);
 void	witness_assert_owner(tsdn_t *tsdn, const witness_t *witness);
 void	witness_assert_not_owner(tsdn_t *tsdn, const witness_t *witness);
+void witness_assert_depth_to_rank(tsdn_t *tsdn, witness_rank_t rank_inclusive,
+    unsigned depth);
+void witness_assert_depth(tsdn_t *tsdn, unsigned depth);
 void	witness_assert_lockless(tsdn_t *tsdn);
 void	witness_lock(tsdn_t *tsdn, witness_t *witness);
 void	witness_unlock(tsdn_t *tsdn, witness_t *witness);
 #endif
 
 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_MUTEX_C_))
 JEMALLOC_INLINE bool
 witness_owner(tsd_t *tsd, const witness_t *witness)
 {
 	witness_list_t *witnesses;
 	witness_t *w;
 
+	cassert(config_debug);
+
 	witnesses = tsd_witnessesp_get(tsd);
 	ql_foreach(w, witnesses, link) {
 		if (w == witness)
 			return (true);
 	}
 
 	return (false);
 }
@@ -170,33 +188,53 @@ witness_assert_not_owner(tsdn_t *tsdn, c
 	witnesses = tsd_witnessesp_get(tsd);
 	ql_foreach(w, witnesses, link) {
 		if (w == witness)
 			witness_not_owner_error(witness);
 	}
 }
 
 JEMALLOC_INLINE void
-witness_assert_lockless(tsdn_t *tsdn)
-{
+witness_assert_depth_to_rank(tsdn_t *tsdn, witness_rank_t rank_inclusive,
+    unsigned depth) {
 	tsd_t *tsd;
+	unsigned d;
 	witness_list_t *witnesses;
 	witness_t *w;
 
 	if (!config_debug)
 		return;
 
 	if (tsdn_null(tsdn))
 		return;
 	tsd = tsdn_tsd(tsdn);
 
+	d = 0;
 	witnesses = tsd_witnessesp_get(tsd);
 	w = ql_last(witnesses, link);
-	if (w != NULL)
-		witness_lockless_error(witnesses);
+	if (w != NULL) {
+		ql_reverse_foreach(w, witnesses, link) {
+			if (w->rank < rank_inclusive) {
+				break;
+			}
+			d++;
+		}
+	}
+	if (d != depth)
+		witness_depth_error(witnesses, rank_inclusive, depth);
+}
+
+JEMALLOC_INLINE void
+witness_assert_depth(tsdn_t *tsdn, unsigned depth) {
+	witness_assert_depth_to_rank(tsdn, WITNESS_RANK_MIN, depth);
+}
+
+JEMALLOC_INLINE void
+witness_assert_lockless(tsdn_t *tsdn) {
+	witness_assert_depth(tsdn, 0);
 }
 
 JEMALLOC_INLINE void
 witness_lock(tsdn_t *tsdn, witness_t *witness)
 {
 	tsd_t *tsd;
 	witness_list_t *witnesses;
 	witness_t *w;
old mode 100755
new mode 100644
new file mode 100755
--- /dev/null
+++ b/memory/jemalloc/src/scripts/gen_travis.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+
+from itertools import combinations
+
+travis_template = """\
+language: generic
+
+matrix:
+  include:
+%s
+
+before_script:
+  - autoconf
+  - ./configure ${COMPILER_FLAGS:+ \
+      CC="$CC $COMPILER_FLAGS" } \
+      $CONFIGURE_FLAGS
+  - make -j3
+  - make -j3 tests
+
+script:
+  - make check
+"""
+
+# The 'default' configuration is gcc, on linux, with no compiler or configure
+# flags.  We also test with clang, -m32, --enable-debug, --enable-prof,
+# --disable-stats, and --disable-tcache.  To avoid abusing travis though, we
+# don't test all 2**7 = 128 possible combinations of these; instead, we only
+# test combinations of up to 2 'unusual' settings, under the hope that bugs
+# involving interactions of such settings are rare.
+# things at once, for C(7, 0) + C(7, 1) + C(7, 2) = 29
+MAX_UNUSUAL_OPTIONS = 2
+
+os_default = 'linux'
+os_unusual = 'osx'
+
+compilers_default = 'CC=gcc'
+compilers_unusual = 'CC=clang'
+
+compiler_flag_unusuals = ['-m32']
+
+configure_flag_unusuals = [
+    '--enable-debug', '--enable-prof', '--disable-stats', '--disable-tcache',
+]
+
+all_unusuals = (
+    [os_unusual] + [compilers_unusual] + compiler_flag_unusuals
+    + configure_flag_unusuals
+)
+
+unusual_combinations_to_test = []
+for i in xrange(MAX_UNUSUAL_OPTIONS + 1):
+    unusual_combinations_to_test += combinations(all_unusuals, i)
+
+include_rows = ""
+for unusual_combination in unusual_combinations_to_test:
+    os = os_default
+    if os_unusual in unusual_combination:
+        os = os_unusual
+
+    compilers = compilers_default
+    if compilers_unusual in unusual_combination:
+        compilers = compilers_unusual
+
+    compiler_flags = [
+        x for x in unusual_combination if x in compiler_flag_unusuals]
+
+    configure_flags = [
+        x for x in unusual_combination if x in configure_flag_unusuals]
+
+    # Filter out an unsupported configuration - heap profiling on OS X.
+    if os == 'osx' and '--enable-prof' in configure_flags:
+        continue
+
+    env_string = '{} COMPILER_FLAGS="{}" CONFIGURE_FLAGS="{}"'.format(
+        compilers, " ".join(compiler_flags), " ".join(configure_flags))
+
+    include_rows += '    - os: %s\n' % os
+    include_rows += '      env: %s\n' % env_string
+    if '-m32' in unusual_combination and os == 'linux':
+        include_rows += '      addons:\n'
+	include_rows += '        apt:\n'
+	include_rows += '          packages:\n'
+	include_rows += '            - gcc-multilib\n'
+
+print travis_template % include_rows
--- a/memory/jemalloc/src/src/arena.c
+++ b/memory/jemalloc/src/src/arena.c
@@ -1,14 +1,16 @@
 #define	JEMALLOC_ARENA_C_
 #include "jemalloc/internal/jemalloc_internal.h"
 
 /******************************************************************************/
 /* Data. */
 
+bool		opt_thp = true;
+static bool	thp_initially_huge;
 purge_mode_t	opt_purge = PURGE_DEFAULT;
 const char	*purge_mode_names[] = {
 	"ratio",
 	"decay",
 	"N/A"
 };
 ssize_t		opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT;
 static ssize_t	lg_dirty_mult_default;
@@ -563,83 +565,99 @@ arena_chunk_init_spare(arena_t *arena)
 	    arena_maxrun);
 	assert(arena_mapbits_dirty_get(chunk, map_bias) ==
 	    arena_mapbits_dirty_get(chunk, chunk_npages-1));
 
 	return (chunk);
 }
 
 static bool
-arena_chunk_register(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk,
-    size_t sn, bool zero)
+arena_chunk_register(arena_t *arena, arena_chunk_t *chunk, size_t sn, bool zero,
+    bool *gdump)
 {
 
 	/*
 	 * The extent node notion of "committed" doesn't directly apply to
 	 * arena chunks.  Arbitrarily mark them as committed.  The commit state
 	 * of runs is tracked individually, and upon chunk deallocation the
 	 * entire chunk is in a consistent commit state.
 	 */
 	extent_node_init(&chunk->node, arena, chunk, chunksize, sn, zero, true);
 	extent_node_achunk_set(&chunk->node, true);
-	return (chunk_register(tsdn, chunk, &chunk->node));
+	return (chunk_register(chunk, &chunk->node, gdump));
 }
 
 static arena_chunk_t *
 arena_chunk_alloc_internal_hard(tsdn_t *tsdn, arena_t *arena,
     chunk_hooks_t *chunk_hooks, bool *zero, bool *commit)
 {
 	arena_chunk_t *chunk;
 	size_t sn;
 
 	malloc_mutex_unlock(tsdn, &arena->lock);
+	/* prof_gdump() requirement. */
+	witness_assert_depth_to_rank(tsdn, WITNESS_RANK_CORE, 0);
 
 	chunk = (arena_chunk_t *)chunk_alloc_wrapper(tsdn, arena, chunk_hooks,
 	    NULL, chunksize, chunksize, &sn, zero, commit);
 	if (chunk != NULL && !*commit) {
 		/* Commit header. */
 		if (chunk_hooks->commit(chunk, chunksize, 0, map_bias <<
 		    LG_PAGE, arena->ind)) {
 			chunk_dalloc_wrapper(tsdn, arena, chunk_hooks,
 			    (void *)chunk, chunksize, sn, *zero, *commit);
 			chunk = NULL;
 		}
 	}
-	if (chunk != NULL && arena_chunk_register(tsdn, arena, chunk, sn,
-	    *zero)) {
-		if (!*commit) {
-			/* Undo commit of header. */
-			chunk_hooks->decommit(chunk, chunksize, 0, map_bias <<
-			    LG_PAGE, arena->ind);
+	if (chunk != NULL) {
+		bool gdump;
+		if (arena_chunk_register(arena, chunk, sn, *zero, &gdump)) {
+			if (!*commit) {
+				/* Undo commit of header. */
+				chunk_hooks->decommit(chunk, chunksize, 0,
+				    map_bias << LG_PAGE, arena->ind);
+			}
+			chunk_dalloc_wrapper(tsdn, arena, chunk_hooks,
+			    (void *)chunk, chunksize, sn, *zero, *commit);
+			chunk = NULL;
 		}
-		chunk_dalloc_wrapper(tsdn, arena, chunk_hooks, (void *)chunk,
-		    chunksize, sn, *zero, *commit);
-		chunk = NULL;
+		if (config_prof && opt_prof && gdump)
+			prof_gdump(tsdn);
 	}
 
 	malloc_mutex_lock(tsdn, &arena->lock);
 	return (chunk);
 }
 
 static arena_chunk_t *
 arena_chunk_alloc_internal(tsdn_t *tsdn, arena_t *arena, bool *zero,
     bool *commit)
 {
 	arena_chunk_t *chunk;
 	chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
 	size_t sn;
 
+	/* prof_gdump() requirement. */
+	witness_assert_depth_to_rank(tsdn, WITNESS_RANK_CORE, 1);
+	malloc_mutex_assert_owner(tsdn, &arena->lock);
+
 	chunk = chunk_alloc_cache(tsdn, arena, &chunk_hooks, NULL, chunksize,
 	    chunksize, &sn, zero, commit, true);
 	if (chunk != NULL) {
-		if (arena_chunk_register(tsdn, arena, chunk, sn, *zero)) {
+		bool gdump;
+		if (arena_chunk_register(arena, chunk, sn, *zero, &gdump)) {
 			chunk_dalloc_cache(tsdn, arena, &chunk_hooks, chunk,
 			    chunksize, sn, true);
 			return (NULL);
 		}
+		if (config_prof && opt_prof && gdump) {
+			malloc_mutex_unlock(tsdn, &arena->lock);
+			prof_gdump(tsdn);
+			malloc_mutex_lock(tsdn, &arena->lock);
+		}
 	}
 	if (chunk == NULL) {
 		chunk = arena_chunk_alloc_internal_hard(tsdn, arena,
 		    &chunk_hooks, zero, commit);
 	}
 
 	if (config_stats && chunk != NULL) {
 		arena->stats.mapped += chunksize;
@@ -659,17 +677,19 @@ arena_chunk_init_hard(tsdn_t *tsdn, aren
 	assert(arena->spare == NULL);
 
 	zero = false;
 	commit = false;
 	chunk = arena_chunk_alloc_internal(tsdn, arena, &zero, &commit);
 	if (chunk == NULL)
 		return (NULL);
 
-	chunk->hugepage = true;
+	if (config_thp && opt_thp) {
+		chunk->hugepage = thp_initially_huge;
+	}
 
 	/*
 	 * Initialize the map to contain one maximal free untouched run.  Mark
 	 * the pages as zeroed if arena_chunk_alloc_internal() returned a zeroed
 	 * or decommitted chunk.
 	 */
 	flag_unzeroed = (zero || !commit) ? 0 : CHUNK_MAP_UNZEROED;
 	flag_decommitted = commit ? 0 : CHUNK_MAP_DECOMMITTED;
@@ -724,43 +744,49 @@ arena_chunk_alloc(tsdn_t *tsdn, arena_t 
 	arena_avail_insert(arena, chunk, map_bias, chunk_npages-map_bias);
 
 	return (chunk);
 }
 
 static void
 arena_chunk_discard(tsdn_t *tsdn, arena_t *arena, arena_chunk_t *chunk)
 {
-	size_t sn, hugepage;
+	size_t sn;
+	UNUSED bool hugepage JEMALLOC_CC_SILENCE_INIT(false);
 	bool committed;
 	chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
 
 	chunk_deregister(chunk, &chunk->node);
 
 	sn = extent_node_sn_get(&chunk->node);
-	hugepage = chunk->hugepage;
+	if (config_thp && opt_thp) {
+		hugepage = chunk->hugepage;
+	}
 	committed = (arena_mapbits_decommitted_get(chunk, map_bias) == 0);
 	if (!committed) {
 		/*
 		 * Decommit the header.  Mark the chunk as decommitted even if
 		 * header decommit fails, since treating a partially committed
 		 * chunk as committed has a high potential for causing later
 		 * access of decommitted memory.
 		 */
 		chunk_hooks = chunk_hooks_get(tsdn, arena);
 		chunk_hooks.decommit(chunk, chunksize, 0, map_bias << LG_PAGE,
 		    arena->ind);
 	}
-	if (!hugepage) {
+	if (config_thp && opt_thp && hugepage != thp_initially_huge) {
 		/*
-		 * Convert chunk back to the default state, so that all
-		 * subsequent chunk allocations start out with chunks that can
-		 * be backed by transparent huge pages.
+		 * Convert chunk back to initial THP state, so that all
+		 * subsequent chunk allocations start out in a consistent state.
 		 */
-		pages_huge(chunk, chunksize);
+		if (thp_initially_huge) {
+			pages_huge(chunk, chunksize);
+		} else {
+			pages_nohuge(chunk, chunksize);
+		}
 	}
 
 	chunk_dalloc_cache(tsdn, arena, &chunk_hooks, (void *)chunk, chunksize,
 	    sn, committed);
 
 	if (config_stats) {
 		arena->stats.mapped -= chunksize;
 		arena->stats.metadata_mapped -= (map_bias << LG_PAGE);
@@ -1690,23 +1716,23 @@ arena_purge_stashed(tsdn_t *tsdn, arena_
 			arena_chunk_map_misc_t *miscelm =
 			    arena_rd_to_miscelm(rdelm);
 			pageind = arena_miscelm_to_pageind(miscelm);
 			run_size = arena_mapbits_large_size_get(chunk, pageind);
 			npages = run_size >> LG_PAGE;
 
 			/*
 			 * If this is the first run purged within chunk, mark
-			 * the chunk as non-huge.  This will prevent all use of
-			 * transparent huge pages for this chunk until the chunk
-			 * as a whole is deallocated.
+			 * the chunk as non-THP-capable.  This will prevent all
+			 * use of THPs for this chunk until the chunk as a whole
+			 * is deallocated.
 			 */
-			if (chunk->hugepage) {
-				pages_nohuge(chunk, chunksize);
-				chunk->hugepage = false;
+			if (config_thp && opt_thp && chunk->hugepage) {
+				chunk->hugepage = pages_nohuge(chunk,
+				    chunksize);
 			}
 
 			assert(pageind + npages <= chunk_npages);
 			assert(!arena_mapbits_decommitted_get(chunk, pageind));
 			assert(!arena_mapbits_decommitted_get(chunk,
 			    pageind+npages-1));
 			decommitted = !chunk_hooks->decommit(chunk, chunksize,
 			    pageind << LG_PAGE, npages << LG_PAGE, arena->ind);
@@ -2689,16 +2715,17 @@ arena_malloc_hard(tsdn_t *tsdn, arena_t 
 		arena = arena_choose(tsdn_tsd(tsdn), arena);
 	if (unlikely(arena == NULL))
 		return (NULL);
 
 	if (likely(size <= SMALL_MAXCLASS))
 		return (arena_malloc_small(tsdn, arena, ind, zero));
 	if (likely(size <= large_maxclass))
 		return (arena_malloc_large(tsdn, arena, ind, zero));
+	assert(index2size(ind) >= chunksize);
 	return (huge_malloc(tsdn, arena, index2size(ind), zero));
 }
 
 /* Only handles large allocations that require more than page alignment. */
 static void *
 arena_palloc_large(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
     bool zero)
 {
@@ -3750,21 +3777,88 @@ bin_info_init(void)
 #define	SC(index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup)	\
 	BIN_INFO_INIT_bin_##bin(index, (ZU(1)<<lg_grp) + (ZU(ndelta)<<lg_delta))
 	SIZE_CLASSES
 #undef BIN_INFO_INIT_bin_yes
 #undef BIN_INFO_INIT_bin_no
 #undef SC
 }
 
+static void
+init_thp_initially_huge(void) {
+	int fd;
+	char buf[sizeof("[always] madvise never\n")];
+	ssize_t nread;
+	static const char *enabled_states[] = {
+		"[always] madvise never\n",
+		"always [madvise] never\n",
+		"always madvise [never]\n"
+	};
+	static const bool thp_initially_huge_states[] = {
+		true,
+		false,
+		false
+	};
+	unsigned i;
+
+	if (config_debug) {
+		for (i = 0; i < sizeof(enabled_states)/sizeof(const char *);
+		    i++) {
+			assert(sizeof(buf) > strlen(enabled_states[i]));
+		}
+	}
+	assert(sizeof(enabled_states)/sizeof(const char *) ==
+	    sizeof(thp_initially_huge_states)/sizeof(bool));
+
+#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_open)
+	fd = (int)syscall(SYS_open,
+	    "/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY);
+#else
+	fd = open("/sys/kernel/mm/transparent_hugepage/enabled", O_RDONLY);
+#endif
+	if (fd == -1) {
+		goto label_error;
+	}
+
+#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_read)
+	nread = (ssize_t)syscall(SYS_read, fd, &buf, sizeof(buf));
+#else
+	nread = read(fd, &buf, sizeof(buf));
+#endif
+
+#if defined(JEMALLOC_USE_SYSCALL) && defined(SYS_close)
+	syscall(SYS_close, fd);
+#else
+	close(fd);
+#endif
+
+	if (nread < 1) {
+		goto label_error;
+	}
+	for (i = 0; i < sizeof(enabled_states)/sizeof(const char *);
+	    i++) {
+		if (strncmp(buf, enabled_states[i], (size_t)nread) == 0) {
+			thp_initially_huge = thp_initially_huge_states[i];
+			return;
+		}
+	}
+
+label_error:
+	thp_initially_huge = false;
+}
+
 void
 arena_boot(void)
 {
 	unsigned i;
 
+	if (config_thp && opt_thp) {
+		init_thp_initially_huge();
+	}
+
 	arena_lg_dirty_mult_default_set(opt_lg_dirty_mult);
 	arena_decay_time_default_set(opt_decay_time);
 
 	/*
 	 * Compute the header size such that it is large enough to contain the
 	 * page map.  The page map is biased to omit entries for the header
 	 * itself, so some iteration is necessary to compute the map bias.
 	 *
@@ -3785,25 +3879,18 @@ arena_boot(void)
 	assert(map_bias > 0);
 
 	map_misc_offset = offsetof(arena_chunk_t, map_bits) +
 	    sizeof(arena_chunk_map_bits_t) * (chunk_npages-map_bias);
 
 	arena_maxrun = chunksize - (map_bias << LG_PAGE);
 	assert(arena_maxrun > 0);
 	large_maxclass = index2size(size2index(chunksize)-1);
-	if (large_maxclass > arena_maxrun) {
-		/*
-		 * For small chunk sizes it's possible for there to be fewer
-		 * non-header pages available than are necessary to serve the
-		 * size classes just below chunksize.
-		 */
-		large_maxclass = arena_maxrun;
-	}
 	assert(large_maxclass > 0);
+	assert(large_maxclass + large_pad <= arena_maxrun);
 	nlclasses = size2index(large_maxclass) - size2index(SMALL_MAXCLASS);
 	nhclasses = NSIZES - nlclasses - NBINS;
 
 	bin_info_init();
 }
 
 void
 arena_prefork0(tsdn_t *tsdn, arena_t *arena)
--- a/memory/jemalloc/src/src/chunk.c
+++ b/memory/jemalloc/src/src/chunk.c
@@ -136,17 +136,17 @@ static void
 chunk_hooks_assure_initialized(tsdn_t *tsdn, arena_t *arena,
     chunk_hooks_t *chunk_hooks)
 {
 
 	chunk_hooks_assure_initialized_impl(tsdn, arena, chunk_hooks, false);
 }
 
 bool
-chunk_register(tsdn_t *tsdn, const void *chunk, const extent_node_t *node)
+chunk_register(const void *chunk, const extent_node_t *node, bool *gdump)
 {
 
 	assert(extent_node_addr_get(node) == chunk);
 
 	if (rtree_set(&chunks_rtree, (uintptr_t)chunk, node))
 		return (true);
 	if (config_prof && opt_prof) {
 		size_t size = extent_node_size_get(node);
@@ -155,18 +155,17 @@ chunk_register(tsdn_t *tsdn, const void 
 		size_t high = atomic_read_z(&highchunks);
 		while (cur > high && atomic_cas_z(&highchunks, high, cur)) {
 			/*
 			 * Don't refresh cur, because it may have decreased
 			 * since this thread lost the highchunks update race.
 			 */
 			high = atomic_read_z(&highchunks);
 		}
-		if (cur > high && prof_gdump_get_unlocked())
-			prof_gdump(tsdn);
+		*gdump = (cur > high && prof_gdump_get_unlocked());
 	}
 
 	return (false);
 }
 
 void
 chunk_deregister(const void *chunk, const extent_node_t *node)
 {
@@ -184,22 +183,27 @@ chunk_deregister(const void *chunk, cons
 
 /*
  * Do first-best-fit chunk selection, i.e. select the oldest/lowest chunk that
  * best fits.
  */
 static extent_node_t *
 chunk_first_best_fit(arena_t *arena, extent_tree_t *chunks_szsnad, size_t size)
 {
+	extent_node_t *node;
+	size_t qsize;
 	extent_node_t key;
 
 	assert(size == CHUNK_CEILING(size));
 
-	extent_node_init(&key, arena, NULL, size, 0, false, false);
-	return (extent_tree_szsnad_nsearch(chunks_szsnad, &key));
+	qsize = extent_size_quantize_ceil(size);
+	extent_node_init(&key, arena, NULL, qsize, 0, false, false);
+	node = extent_tree_szsnad_nsearch(chunks_szsnad, &key);
+	assert(node == NULL || extent_node_size_get(node) >= size);
+	return node;
 }
 
 static void *
 chunk_recycle(tsdn_t *tsdn, arena_t *arena, chunk_hooks_t *chunk_hooks,
     extent_tree_t *chunks_szsnad, extent_tree_t *chunks_ad, bool cache,
     void *new_addr, size_t size, size_t alignment, size_t *sn, bool *zero,
     bool *commit, bool dalloc_node)
 {
--- a/memory/jemalloc/src/src/chunk_dss.c
+++ b/memory/jemalloc/src/src/chunk_dss.c
@@ -110,63 +110,72 @@ chunk_alloc_dss(tsdn_t *tsdn, arena_t *a
 
 	if (!atomic_read_u(&dss_exhausted)) {
 		/*
 		 * The loop is necessary to recover from races with other
 		 * threads that are using the DSS for something other than
 		 * malloc.
 		 */
 		while (true) {
-			void *ret, *cpad, *max_cur, *dss_next, *dss_prev;
-			size_t gap_size, cpad_size;
+			void *ret, *max_cur, *dss_next, *dss_prev;
+			void *gap_addr_chunk, *gap_addr_subchunk;
+			size_t gap_size_chunk, gap_size_subchunk;
 			intptr_t incr;
 
 			max_cur = chunk_dss_max_update(new_addr);
 			if (max_cur == NULL)
 				goto label_oom;
 
 			/*
-			 * Calculate how much padding is necessary to
-			 * chunk-align the end of the DSS.
-			 */
-			gap_size = (chunksize - CHUNK_ADDR2OFFSET(dss_max)) &
-			    chunksize_mask;
-			/*
-			 * Compute how much chunk-aligned pad space (if any) is
+			 * Compute how much chunk-aligned gap space (if any) is
 			 * necessary to satisfy alignment.  This space can be
 			 * recycled for later use.
 			 */
-			cpad = (void *)((uintptr_t)dss_max + gap_size);
-			ret = (void *)ALIGNMENT_CEILING((uintptr_t)dss_max,
-			    alignment);
-			cpad_size = (uintptr_t)ret - (uintptr_t)cpad;
+			gap_addr_chunk = (void *)(CHUNK_CEILING(
+			    (uintptr_t)max_cur));
+			ret = (void *)ALIGNMENT_CEILING(
+			    (uintptr_t)gap_addr_chunk, alignment);
+			gap_size_chunk = (uintptr_t)ret -
+			    (uintptr_t)gap_addr_chunk;
+			/*
+			 * Compute the address just past the end of the desired
+			 * allocation space.
+			 */
 			dss_next = (void *)((uintptr_t)ret + size);
-			if ((uintptr_t)ret < (uintptr_t)dss_max ||
-			    (uintptr_t)dss_next < (uintptr_t)dss_max)
+			if ((uintptr_t)ret < (uintptr_t)max_cur ||
+			    (uintptr_t)dss_next < (uintptr_t)max_cur)
 				goto label_oom; /* Wrap-around. */
-			incr = gap_size + cpad_size + size;
+			/* Compute the increment, including subchunk bytes. */
+			gap_addr_subchunk = max_cur;
+			gap_size_subchunk = (uintptr_t)ret -
+			    (uintptr_t)gap_addr_subchunk;
+			incr = gap_size_subchunk + size;
+
+			assert((uintptr_t)max_cur + incr == (uintptr_t)ret +
+			    size);
 
 			/*
 			 * Optimistically update dss_max, and roll back below if
 			 * sbrk() fails.  No other thread will try to extend the
 			 * DSS while dss_max is greater than the current DSS
 			 * max reported by sbrk(0).
 			 */
 			if (atomic_cas_p(&dss_max, max_cur, dss_next))
 				continue;
 
 			/* Try to allocate. */
 			dss_prev = chunk_dss_sbrk(incr);
 			if (dss_prev == max_cur) {
 				/* Success. */
-				if (cpad_size != 0) {
+				if (gap_size_chunk != 0) {
 					chunk_hooks_t chunk_hooks =
 					    CHUNK_HOOKS_INITIALIZER;
 					chunk_dalloc_wrapper(tsdn, arena,
-					    &chunk_hooks, cpad, cpad_size,
+					    &chunk_hooks, gap_addr_chunk,
+					    gap_size_chunk,
 					    arena_extent_sn_next(arena), false,
 					    true);
 				}
 				if (*zero) {
 					JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(
 					    ret, size);
 					memset(ret, 0, size);
 				}
--- a/memory/jemalloc/src/src/ctl.c
+++ b/memory/jemalloc/src/src/ctl.c
@@ -79,16 +79,17 @@ CTL_PROTO(config_fill)
 CTL_PROTO(config_lazy_lock)
 CTL_PROTO(config_malloc_conf)
 CTL_PROTO(config_munmap)
 CTL_PROTO(config_prof)
 CTL_PROTO(config_prof_libgcc)
 CTL_PROTO(config_prof_libunwind)
 CTL_PROTO(config_stats)
 CTL_PROTO(config_tcache)
+CTL_PROTO(config_thp)
 CTL_PROTO(config_tls)
 CTL_PROTO(config_utrace)
 CTL_PROTO(config_valgrind)
 CTL_PROTO(config_xmalloc)
 CTL_PROTO(opt_abort)
 CTL_PROTO(opt_dss)
 CTL_PROTO(opt_lg_chunk)
 CTL_PROTO(opt_narenas)
@@ -99,16 +100,17 @@ CTL_PROTO(opt_stats_print)
 CTL_PROTO(opt_junk)
 CTL_PROTO(opt_zero)
 CTL_PROTO(opt_quarantine)
 CTL_PROTO(opt_redzone)
 CTL_PROTO(opt_utrace)
 CTL_PROTO(opt_xmalloc)
 CTL_PROTO(opt_tcache)
 CTL_PROTO(opt_lg_tcache_max)
+CTL_PROTO(opt_thp)
 CTL_PROTO(opt_prof)
 CTL_PROTO(opt_prof_prefix)
 CTL_PROTO(opt_prof_active)
 CTL_PROTO(opt_prof_thread_active_init)
 CTL_PROTO(opt_lg_prof_sample)
 CTL_PROTO(opt_lg_prof_interval)
 CTL_PROTO(opt_prof_gdump)
 CTL_PROTO(opt_prof_final)
@@ -253,16 +255,17 @@ static const ctl_named_node_t	config_nod
 	{NAME("lazy_lock"),	CTL(config_lazy_lock)},
 	{NAME("malloc_conf"),	CTL(config_malloc_conf)},
 	{NAME("munmap"),	CTL(config_munmap)},
 	{NAME("prof"),		CTL(config_prof)},
 	{NAME("prof_libgcc"),	CTL(config_prof_libgcc)},
 	{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
 	{NAME("stats"),		CTL(config_stats)},
 	{NAME("tcache"),	CTL(config_tcache)},
+	{NAME("thp"),		CTL(config_thp)},
 	{NAME("tls"),		CTL(config_tls)},
 	{NAME("utrace"),	CTL(config_utrace)},
 	{NAME("valgrind"),	CTL(config_valgrind)},
 	{NAME("xmalloc"),	CTL(config_xmalloc)}
 };
 
 static const ctl_named_node_t opt_node[] = {
 	{NAME("abort"),		CTL(opt_abort)},
@@ -276,16 +279,17 @@ static const ctl_named_node_t opt_node[]
 	{NAME("junk"),		CTL(opt_junk)},
 	{NAME("zero"),		CTL(opt_zero)},
 	{NAME("quarantine"),	CTL(opt_quarantine)},
 	{NAME("redzone"),	CTL(opt_redzone)},
 	{NAME("utrace"),	CTL(opt_utrace)},
 	{NAME("xmalloc"),	CTL(opt_xmalloc)},
 	{NAME("tcache"),	CTL(opt_tcache)},
 	{NAME("lg_tcache_max"),	CTL(opt_lg_tcache_max)},
+	{NAME("thp"),		CTL(opt_thp)},
 	{NAME("prof"),		CTL(opt_prof)},
 	{NAME("prof_prefix"),	CTL(opt_prof_prefix)},
 	{NAME("prof_active"),	CTL(opt_prof_active)},
 	{NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)},
 	{NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
 	{NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
 	{NAME("prof_gdump"),	CTL(opt_prof_gdump)},
 	{NAME("prof_final"),	CTL(opt_prof_final)},
@@ -1263,16 +1267,17 @@ CTL_RO_CONFIG_GEN(config_fill, bool)
 CTL_RO_CONFIG_GEN(config_lazy_lock, bool)
 CTL_RO_CONFIG_GEN(config_malloc_conf, const char *)
 CTL_RO_CONFIG_GEN(config_munmap, bool)
 CTL_RO_CONFIG_GEN(config_prof, bool)
 CTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
 CTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
 CTL_RO_CONFIG_GEN(config_stats, bool)
 CTL_RO_CONFIG_GEN(config_tcache, bool)
+CTL_RO_CONFIG_GEN(config_thp, bool)
 CTL_RO_CONFIG_GEN(config_tls, bool)
 CTL_RO_CONFIG_GEN(config_utrace, bool)
 CTL_RO_CONFIG_GEN(config_valgrind, bool)
 CTL_RO_CONFIG_GEN(config_xmalloc, bool)
 
 /******************************************************************************/
 
 CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
@@ -1286,16 +1291,17 @@ CTL_RO_NL_GEN(opt_stats_print, opt_stats
 CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)
 CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
 CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
 CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
 CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
 CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
 CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
 CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
+CTL_RO_NL_CGEN(config_thp, opt_thp, opt_thp, bool)
 CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
 CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
 CTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)
 CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
     opt_prof_thread_active_init, bool)
 CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
 CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
 CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
@@ -1471,28 +1477,26 @@ tcache_create_ctl(tsd_t *tsd, const size
     size_t *oldlenp, void *newp, size_t newlen)
 {
 	int ret;
 	unsigned tcache_ind;
 
 	if (!config_tcache)
 		return (ENOENT);
 
-	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
 	READONLY();
 	if (tcaches_create(tsd, &tcache_ind)) {
 		ret = EFAULT;
 		goto label_return;
 	}
 	READ(tcache_ind, unsigned);
 
 	ret = 0;
 label_return:
-	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
-	return (ret);
+	return ret;
 }
 
 static int
 tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
     size_t *oldlenp, void *newp, size_t newlen)
 {
 	int ret;
 	unsigned tcache_ind;
--- a/memory/jemalloc/src/src/extent.c
+++ b/memory/jemalloc/src/src/extent.c
@@ -1,40 +1,59 @@
 #define	JEMALLOC_EXTENT_C_
 #include "jemalloc/internal/jemalloc_internal.h"
 
 /******************************************************************************/
 
-/*
- * Round down to the nearest chunk size that can actually be requested during
- * normal huge allocation.
- */
-JEMALLOC_INLINE_C size_t
-extent_quantize(size_t size)
-{
+#ifndef JEMALLOC_JET
+static
+#endif
+size_t
+extent_size_quantize_floor(size_t size) {
 	size_t ret;
 	szind_t ind;
 
 	assert(size > 0);
 
 	ind = size2index(size + 1);
 	if (ind == 0) {
 		/* Avoid underflow. */
 		return (index2size(0));
 	}
 	ret = index2size(ind - 1);
 	assert(ret <= size);
 	return (ret);
 }
 
+size_t
+extent_size_quantize_ceil(size_t size) {
+	size_t ret;
+
+	assert(size > 0);
+
+	ret = extent_size_quantize_floor(size);
+	if (ret < size) {
+		/*
+		 * Skip a quantization that may have an adequately large extent,
+		 * because under-sized extents may be mixed in.  This only
+		 * happens when an unusual size is requested, i.e. for aligned
+		 * allocation, and is just one of several places where linear
+		 * search would potentially find sufficiently aligned available
+		 * memory somewhere lower.
+		 */
+		ret = index2size(size2index(ret  + 1));
+	}
+	return ret;
+}
+
 JEMALLOC_INLINE_C int
 extent_sz_comp(const extent_node_t *a, const extent_node_t *b)
 {
-	size_t a_qsize = extent_quantize(extent_node_size_get(a));
-	size_t b_qsize = extent_quantize(extent_node_size_get(b));
+	size_t a_qsize = extent_size_quantize_floor(extent_node_size_get(a));
+	size_t b_qsize = extent_size_quantize_floor(extent_node_size_get(b));
 
 	return ((a_qsize > b_qsize) - (a_qsize < b_qsize));
 }
 
 JEMALLOC_INLINE_C int
 extent_sn_comp(const extent_node_t *a, const extent_node_t *b)
 {
 	size_t a_sn = extent_node_sn_get(a);
--- a/memory/jemalloc/src/src/huge.c
+++ b/memory/jemalloc/src/src/huge.c
@@ -10,30 +10,30 @@ huge_node_get(const void *ptr)
 
 	node = chunk_lookup(ptr, true);
 	assert(!extent_node_achunk_get(node));
 
 	return (node);
 }
 
 static bool
-huge_node_set(tsdn_t *tsdn, const void *ptr, extent_node_t *node)
+huge_node_set(tsdn_t *tsdn, const void *ptr, extent_node_t *node, bool *gdump)
 {
 
 	assert(extent_node_addr_get(node) == ptr);
 	assert(!extent_node_achunk_get(node));
-	return (chunk_register(tsdn, ptr, node));
+	return (chunk_register(ptr, node, gdump));
 }
 
 static void
-huge_node_reset(tsdn_t *tsdn, const void *ptr, extent_node_t *node)
+huge_node_reset(tsdn_t *tsdn, const void *ptr, extent_node_t *node, bool *gdump)
 {
 	bool err;
 
-	err = huge_node_set(tsdn, ptr, node);
+	err = huge_node_set(tsdn, ptr, node, gdump);
 	assert(!err);
 }
 
 static void
 huge_node_unset(const void *ptr, const extent_node_t *node)
 {
 
 	chunk_deregister(ptr, node);
@@ -52,21 +52,23 @@ void *
 huge_palloc(tsdn_t *tsdn, arena_t *arena, size_t usize, size_t alignment,
     bool zero)
 {
 	void *ret;
 	size_t ausize;
 	arena_t *iarena;
 	extent_node_t *node;
 	size_t sn;
-	bool is_zeroed;
+	bool is_zeroed, gdump;
 
 	/* Allocate one or more contiguous chunks for this request. */
 
 	assert(!tsdn_null(tsdn) || arena != NULL);
+	/* prof_gdump() requirement. */
+	witness_assert_depth_to_rank(tsdn, WITNESS_RANK_CORE, 0);
 
 	ausize = sa2u(usize, alignment);
 	if (unlikely(ausize == 0 || ausize > HUGE_MAXCLASS))
 		return (NULL);
 	assert(ausize >= chunksize);
 
 	/* Allocate an extent node with which to track the chunk. */
 	iarena = (!tsdn_null(tsdn)) ? arena_ichoose(tsdn_tsd(tsdn), NULL) :
@@ -86,21 +88,23 @@ huge_palloc(tsdn_t *tsdn, arena_t *arena
 	if (unlikely(arena == NULL) || (ret = arena_chunk_alloc_huge(tsdn,
 	    arena, usize, alignment, &sn, &is_zeroed)) == NULL) {
 		idalloctm(tsdn, node, NULL, true, true);
 		return (NULL);
 	}
 
 	extent_node_init(node, arena, ret, usize, sn, is_zeroed, true);
 
-	if (huge_node_set(tsdn, ret, node)) {
+	if (huge_node_set(tsdn, ret, node, &gdump)) {
 		arena_chunk_dalloc_huge(tsdn, arena, ret, usize, sn);
 		idalloctm(tsdn, node, NULL, true, true);
 		return (NULL);
 	}
+	if (config_prof && opt_prof && gdump)
+		prof_gdump(tsdn);
 
 	/* Insert node into huge. */
 	malloc_mutex_lock(tsdn, &arena->huge_mtx);
 	ql_elm_new(node, ql_link);
 	ql_tail_insert(&arena->huge, node, ql_link);
 	malloc_mutex_unlock(tsdn, &arena->huge_mtx);
 
 	if (zero || (config_fill && unlikely(opt_zero))) {
@@ -139,17 +143,20 @@ huge_dalloc_junk_t *huge_dalloc_junk = J
 static void
 huge_ralloc_no_move_similar(tsdn_t *tsdn, void *ptr, size_t oldsize,
     size_t usize_min, size_t usize_max, bool zero)
 {
 	size_t usize, usize_next;
 	extent_node_t *node;
 	arena_t *arena;
 	chunk_hooks_t chunk_hooks = CHUNK_HOOKS_INITIALIZER;
-	bool pre_zeroed, post_zeroed;
+	bool pre_zeroed, post_zeroed, gdump;
+
+	/* prof_gdump() requirement. */
+	witness_assert_depth_to_rank(tsdn, WITNESS_RANK_CORE, 0);
 
 	/* Increase usize to incorporate extra. */
 	for (usize = usize_min; usize < usize_max && (usize_next = s2u(usize+1))
 	    <= oldsize; usize = usize_next)
 		; /* Do nothing. */
 
 	if (oldsize == usize)
 		return;
@@ -173,20 +180,23 @@ huge_ralloc_no_move_similar(tsdn_t *tsdn
 	} else
 		post_zeroed = pre_zeroed;
 
 	malloc_mutex_lock(tsdn, &arena->huge_mtx);
 	/* Update the size of the huge allocation. */
 	huge_node_unset(ptr, node);
 	assert(extent_node_size_get(node) != usize);
 	extent_node_size_set(node, usize);
-	huge_node_reset(tsdn, ptr, node);
+	huge_node_reset(tsdn, ptr, node, &gdump);
 	/* Update zeroed. */
 	extent_node_zeroed_set(node, post_zeroed);
 	malloc_mutex_unlock(tsdn, &arena->huge_mtx);
+	/* gdump without any locks held. */
+	if (config_prof && opt_prof && gdump)
+		prof_gdump(tsdn);
 
 	arena_chunk_ralloc_huge_similar(tsdn, arena, ptr, oldsize, usize);
 
 	/* Fill if necessary (growing). */
 	if (oldsize < usize) {
 		if (zero || (config_fill && unlikely(opt_zero))) {
 			if (!pre_zeroed) {
 				memset((void *)((uintptr_t)ptr + oldsize), 0,
@@ -202,24 +212,26 @@ huge_ralloc_no_move_similar(tsdn_t *tsdn
 static bool
 huge_ralloc_no_move_shrink(tsdn_t *tsdn, void *ptr, size_t oldsize,
     size_t usize)
 {
 	extent_node_t *node;
 	arena_t *arena;
 	chunk_hooks_t chunk_hooks;
 	size_t cdiff;
-	bool pre_zeroed, post_zeroed;
+	bool pre_zeroed, post_zeroed, gdump;
 
 	node = huge_node_get(ptr);
 	arena = extent_node_arena_get(node);
 	pre_zeroed = extent_node_zeroed_get(node);
 	chunk_hooks = chunk_hooks_get(tsdn, arena);
 
 	assert(oldsize > usize);
+	/* prof_gdump() requirement. */
+	witness_assert_depth_to_rank(tsdn, WITNESS_RANK_CORE, 0);
 
 	/* Split excess chunks. */
 	cdiff = CHUNK_CEILING(oldsize) - CHUNK_CEILING(usize);
 	if (cdiff != 0 && chunk_hooks.split(ptr, CHUNK_CEILING(oldsize),
 	    CHUNK_CEILING(usize), cdiff, true, arena->ind))
 		return (true);
 
 	if (oldsize > usize) {
@@ -236,57 +248,66 @@ huge_ralloc_no_move_shrink(tsdn_t *tsdn,
 		}
 	} else
 		post_zeroed = pre_zeroed;
 
 	malloc_mutex_lock(tsdn, &arena->huge_mtx);
 	/* Update the size of the huge allocation. */
 	huge_node_unset(ptr, node);
 	extent_node_size_set(node, usize);
-	huge_node_reset(tsdn, ptr, node);
+	huge_node_reset(tsdn, ptr, node, &gdump);
 	/* Update zeroed. */
 	extent_node_zeroed_set(node, post_zeroed);
 	malloc_mutex_unlock(tsdn, &arena->huge_mtx);
+	/* gdump without any locks held. */
+	if (config_prof && opt_prof && gdump)
+		prof_gdump(tsdn);
 
 	/* Zap the excess chunks. */
 	arena_chunk_ralloc_huge_shrink(tsdn, arena, ptr, oldsize, usize,
 	    extent_node_sn_get(node));
 
 	return (false);
 }
 
 static bool
 huge_ralloc_no_move_expand(tsdn_t *tsdn, void *ptr, size_t oldsize,
     size_t usize, bool zero) {
 	extent_node_t *node;
 	arena_t *arena;
-	bool is_zeroed_subchunk, is_zeroed_chunk;
+	bool is_zeroed_subchunk, is_zeroed_chunk, gdump;
 
 	node = huge_node_get(ptr);
 	arena = extent_node_arena_get(node);
 	malloc_mutex_lock(tsdn, &arena->huge_mtx);
 	is_zeroed_subchunk = extent_node_zeroed_get(node);
 	malloc_mutex_unlock(tsdn, &arena->huge_mtx);
 
+	/* prof_gdump() requirement. */
+	witness_assert_depth_to_rank(tsdn, WITNESS_RANK_CORE, 0);
+
 	/*
 	 * Use is_zeroed_chunk to detect whether the trailing memory is zeroed,
 	 * update extent's zeroed field, and zero as necessary.
 	 */
 	is_zeroed_chunk = false;
 	if (arena_chunk_ralloc_huge_expand(tsdn, arena, ptr, oldsize, usize,
 	     &is_zeroed_chunk))
 		return (true);
 
 	malloc_mutex_lock(tsdn, &arena->huge_mtx);
 	huge_node_unset(ptr, node);
 	extent_node_size_set(node, usize);
 	extent_node_zeroed_set(node, extent_node_zeroed_get(node) &&
 	    is_zeroed_chunk);
-	huge_node_reset(tsdn, ptr, node);
+	huge_node_reset(tsdn, ptr, node, &gdump);
 	malloc_mutex_unlock(tsdn, &arena->huge_mtx);
+	/* gdump without any locks held. */
+	if (config_prof && opt_prof && gdump)
+		prof_gdump(tsdn);
 
 	if (zero || (config_fill && unlikely(opt_zero))) {
 		if (!is_zeroed_subchunk) {
 			memset((void *)((uintptr_t)ptr + oldsize), 0,
 			    CHUNK_CEILING(oldsize) - oldsize);
 		}
 		if (!is_zeroed_chunk) {
 			memset((void *)((uintptr_t)ptr +
--- a/memory/jemalloc/src/src/jemalloc.c
+++ b/memory/jemalloc/src/src/jemalloc.c
@@ -785,28 +785,29 @@ stats_print_atexit(void)
 /*
  * End miscellaneous support functions.
  */
 /******************************************************************************/
 /*
  * Begin initialization functions.
  */
 
-#ifndef JEMALLOC_HAVE_SECURE_GETENV
 static char *
-secure_getenv(const char *name)
+jemalloc_secure_getenv(const char *name)
 {
-
+#ifdef JEMALLOC_HAVE_SECURE_GETENV
+	return secure_getenv(name);
+#else
 #  ifdef JEMALLOC_HAVE_ISSETUGID
 	if (issetugid() != 0)
 		return (NULL);
 #  endif
 	return (getenv(name));
+#endif
 }
-#endif
 
 static unsigned
 malloc_ncpus(void)
 {
 	long result;
 
 #ifdef _WIN32
 	SYSTEM_INFO si;
@@ -1013,17 +1014,17 @@ malloc_conf_init(void)
 			const char *envname =
 #ifdef JEMALLOC_PREFIX
 			    JEMALLOC_CPREFIX"MALLOC_CONF"
 #else
 			    "MALLOC_CONF"
 #endif
 			    ;
 
-			if ((opts = secure_getenv(envname)) != NULL) {
+			if ((opts = jemalloc_secure_getenv(envname)) != NULL) {
 				/*
 				 * Do nothing; opts is already initialized to
 				 * the value of the MALLOC_CONF environment
 				 * variable.
 				 */
 			} else {
 				/* No configuration specified. */
 				buf[0] = '\0';
@@ -1069,28 +1070,28 @@ malloc_conf_init(void)
 				um = malloc_strtoumax(v, &end, 0);	\
 				if (get_errno() != 0 || (uintptr_t)end -\
 				    (uintptr_t)v != vlen) {		\
 					malloc_conf_error(		\
 					    "Invalid conf value",	\
 					    k, klen, v, vlen);		\
 				} else if (clip) {			\
 					if (CONF_MIN_##check_min(um,	\
-					    (min)))			\
+					    (t)(min)))			\
 						o = (t)(min);		\
 					else if (CONF_MAX_##check_max(	\
-					    um, (max)))			\
+					    um, (t)(max)))		\
 						o = (t)(max);		\
 					else				\
 						o = (t)um;		\
 				} else {				\
 					if (CONF_MIN_##check_min(um,	\
-					    (min)) ||			\
+					    (t)(min)) ||		\
 					    CONF_MAX_##check_max(um,	\
-					    (max))) {			\
+					    (t)(max))) {		\
 						malloc_conf_error(	\
 						    "Out-of-range "	\
 						    "conf value",	\
 						    k, klen, v, vlen);	\
 					} else				\
 						o = (t)um;		\
 				}					\
 				continue;				\
@@ -1130,26 +1131,28 @@ malloc_conf_init(void)
 				    sizeof(o)-1;			\
 				strncpy(o, v, cpylen);			\
 				o[cpylen] = '\0';			\
 				continue;				\
 			}
 
 			CONF_HANDLE_BOOL(opt_abort, "abort", true)
 			/*
-			 * Chunks always require at least one header page,
-			 * as many as 2^(LG_SIZE_CLASS_GROUP+1) data pages, and
-			 * possibly an additional page in the presence of
-			 * redzones.  In order to simplify options processing,
-			 * use a conservative bound that accommodates all these
-			 * constraints.
+			 * Chunks always require at least one header page, as
+			 * many as 2^(LG_SIZE_CLASS_GROUP+1) data pages (plus an
+			 * additional page in the presence of cache-oblivious
+			 * large), and possibly an additional page in the
+			 * presence of redzones.  In order to simplify options
+			 * processing, use a conservative bound that
+			 * accommodates all these constraints.
 			 */
 			CONF_HANDLE_SIZE_T(opt_lg_chunk, "lg_chunk", LG_PAGE +
-			    LG_SIZE_CLASS_GROUP + (config_fill ? 2 : 1),
-			    (sizeof(size_t) << 3) - 1, yes, yes, true)
+			    LG_SIZE_CLASS_GROUP + 1 + ((config_cache_oblivious
+			    || config_fill) ? 1 : 0), (sizeof(size_t) << 3) - 1,
+			    yes, yes, true)
 			if (strncmp("dss", k, klen) == 0) {
 				int i;
 				bool match = false;
 				for (i = 0; i < dss_prec_limit; i++) {
 					if (strncmp(dss_prec_names[i], v, vlen)
 					    == 0) {
 						if (chunk_dss_prec_set(i)) {
 							malloc_conf_error(
@@ -1264,16 +1267,19 @@ malloc_conf_init(void)
 						k, klen, v, vlen);
 					}
 					continue;
 				}
 				CONF_HANDLE_SSIZE_T(opt_lg_tcache_max,
 				    "lg_tcache_max", -1,
 				    (sizeof(size_t) << 3) - 1)
 			}
+			if (config_thp) {
+				CONF_HANDLE_BOOL(opt_thp, "thp", true)
+			}
 			if (config_prof) {
 				CONF_HANDLE_BOOL(opt_prof, "prof", true)
 				CONF_HANDLE_CHAR_P(opt_prof_prefix,
 				    "prof_prefix", "jeprof")
 				CONF_HANDLE_BOOL(opt_prof_active, "prof_active",
 				    true)
 				CONF_HANDLE_BOOL(opt_prof_thread_active_init,
 				    "prof_thread_active_init", true)
@@ -2822,16 +2828,17 @@ JEMALLOC_EXPORT void
 
 	tsd = tsd_fetch();
 
 	narenas = narenas_total_get();
 
 	witness_prefork(tsd);
 	/* Acquire all mutexes in a safe order. */
 	ctl_prefork(tsd_tsdn(tsd));
+	tcache_prefork(tsd_tsdn(tsd));
 	malloc_mutex_prefork(tsd_tsdn(tsd), &arenas_lock);
 	prof_prefork0(tsd_tsdn(tsd));
 	for (i = 0; i < 3; i++) {
 		for (j = 0; j < narenas; j++) {
 			if ((arena = arena_get(tsd_tsdn(tsd), j, false)) !=
 			    NULL) {
 				switch (i) {
 				case 0:
@@ -2881,16 +2888,17 @@ JEMALLOC_EXPORT void
 	for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
 		arena_t *arena;
 
 		if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
 			arena_postfork_parent(tsd_tsdn(tsd), arena);
 	}
 	prof_postfork_parent(tsd_tsdn(tsd));
 	malloc_mutex_postfork_parent(tsd_tsdn(tsd), &arenas_lock);
+	tcache_postfork_parent(tsd_tsdn(tsd));
 	ctl_postfork_parent(tsd_tsdn(tsd));
 }
 
 void
 jemalloc_postfork_child(void)
 {
 	tsd_t *tsd;
 	unsigned i, narenas;
@@ -2905,12 +2913,13 @@ jemalloc_postfork_child(void)
 	for (i = 0, narenas = narenas_total_get(); i < narenas; i++) {
 		arena_t *arena;
 
 		if ((arena = arena_get(tsd_tsdn(tsd), i, false)) != NULL)
 			arena_postfork_child(tsd_tsdn(tsd), arena);
 	}
 	prof_postfork_child(tsd_tsdn(tsd));
 	malloc_mutex_postfork_child(tsd_tsdn(tsd), &arenas_lock);
+	tcache_postfork_child(tsd_tsdn(tsd));
 	ctl_postfork_child(tsd_tsdn(tsd));
 }
 
 /******************************************************************************/
--- a/memory/jemalloc/src/src/pages.c
+++ b/memory/jemalloc/src/src/pages.c
@@ -194,31 +194,31 @@ pages_purge(void *addr, size_t size)
 
 bool
 pages_huge(void *addr, size_t size)
 {
 
 	assert(PAGE_ADDR2BASE(addr) == addr);
 	assert(PAGE_CEILING(size) == size);
 
-#ifdef JEMALLOC_THP
+#ifdef JEMALLOC_HAVE_MADVISE_HUGE
 	return (madvise(addr, size, MADV_HUGEPAGE) != 0);
 #else
 	return (false);
 #endif
 }
 
 bool
 pages_nohuge(void *addr, size_t size)
 {
 
 	assert(PAGE_ADDR2BASE(addr) == addr);
 	assert(PAGE_CEILING(size) == size);
 
-#ifdef JEMALLOC_THP
+#ifdef JEMALLOC_HAVE_MADVISE_HUGE
 	return (madvise(addr, size, MADV_NOHUGEPAGE) != 0);
 #else
 	return (false);
 #endif
 }
 
 #ifdef JEMALLOC_SYSCTL_VM_OVERCOMMIT
 static bool
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/src/stats.c
+++ b/memory/jemalloc/src/src/stats.c
@@ -34,27 +34,26 @@ size_t	stats_cactive = 0;
 
 /******************************************************************************/
 
 static void
 stats_arena_bins_print(void (*write_cb)(void *, const char *), void *cbopaque,
     bool json, bool large, bool huge, unsigned i)
 {
 	size_t page;
-	bool config_tcache, in_gap, in_gap_prev;
+	bool in_gap, in_gap_prev;
 	unsigned nbins, j;
 
 	CTL_GET("arenas.page", &page, size_t);
 
 	CTL_GET("arenas.nbins", &nbins, unsigned);
 	if (json) {
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\t\"bins\": [\n");
 	} else {
-		CTL_GET("config.tcache", &config_tcache, bool);
 		if (config_tcache) {
 			malloc_cprintf(write_cb, cbopaque,
 			    "bins:           size ind    allocated      nmalloc"
 			    "      ndalloc    nrequests      curregs"
 			    "      curruns regs pgs  util       nfills"
 			    "     nflushes      newruns       reruns\n");
 		} else {
 			malloc_cprintf(write_cb, cbopaque,
@@ -132,28 +131,38 @@ stats_arena_bins_print(void (*write_cb)(
 			    (j + 1 < nbins) ? "," : "");
 		} else if (!in_gap) {
 			size_t availregs, milli;
 			char util[6]; /* "x.yyy". */
 
 			availregs = nregs * curruns;
 			milli = (availregs != 0) ? (1000 * curregs) / availregs
 			    : 1000;
-			assert(milli <= 1000);
-			if (milli < 10) {
+
+			if (milli > 1000) {
+				/*
+				 * Race detected: the counters were read in
+				 * separate mallctl calls and concurrent
+				 * operations happened in between. In this case
+				 * no meaningful utilization can be computed.
+				 */
+				malloc_snprintf(util, sizeof(util), " race");
+			} else if (milli < 10) {
 				malloc_snprintf(util, sizeof(util),
 				    "0.00%zu", milli);
 			} else if (milli < 100) {
 				malloc_snprintf(util, sizeof(util), "0.0%zu",
 				    milli);
 			} else if (milli < 1000) {
 				malloc_snprintf(util, sizeof(util), "0.%zu",
 				    milli);
-			} else
+			} else {
+				assert(milli == 1000);
 				malloc_snprintf(util, sizeof(util), "1");
+			}
 
 			if (config_tcache) {
 				malloc_cprintf(write_cb, cbopaque,
 				    "%20zu %3u %12zu %12"FMTu64
 				    " %12"FMTu64" %12"FMTu64" %12zu"
 				    " %12zu %4u %3zu %-5s %12"FMTu64
 				    " %12"FMTu64" %12"FMTu64" %12"FMTu64"\n",
 				    reg_size, j, curregs * reg_size, nmalloc,
@@ -531,17 +540,17 @@ stats_arena_print(void (*write_cb)(void 
 		    "\t\t\t\t\"metadata\": {\n");
 
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\t\t\"mapped\": %zu,\n", metadata_mapped);
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\t\t\"allocated\": %zu\n", metadata_allocated);
 
 		malloc_cprintf(write_cb, cbopaque,
-		    "\t\t\t\t},\n");
+		    "\t\t\t\t}%s\n", (bins || large || huge) ? "," : "");
 	} else {
 		malloc_cprintf(write_cb, cbopaque,
 		    "metadata: mapped: %zu, allocated: %zu\n",
 		    metadata_mapped, metadata_allocated);
 	}
 
 	if (bins) {
 		stats_arena_bins_print(write_cb, cbopaque, json, large, huge,
@@ -550,17 +559,17 @@ stats_arena_print(void (*write_cb)(void 
 	if (large)
 		stats_arena_lruns_print(write_cb, cbopaque, json, huge, i);
 	if (huge)
 		stats_arena_hchunks_print(write_cb, cbopaque, json, i);
 }
 
 static void
 stats_general_print(void (*write_cb)(void *, const char *), void *cbopaque,
-    bool json, bool merged, bool unmerged)
+    bool json, bool more)
 {
 	const char *cpv;
 	bool bv;
 	unsigned uv;
 	uint32_t u32v;
 	uint64_t u64v;
 	ssize_t ssv;
 	size_t sv, bsz, usz, ssz, sssz, cpsz;
@@ -736,16 +745,17 @@ stats_general_print(void (*write_cb)(voi
 	OPT_WRITE_CHAR_P(junk, ",")
 	OPT_WRITE_SIZE_T(quarantine, ",")
 	OPT_WRITE_BOOL(redzone, ",")
 	OPT_WRITE_BOOL(zero, ",")
 	OPT_WRITE_BOOL(utrace, ",")
 	OPT_WRITE_BOOL(xmalloc, ",")
 	OPT_WRITE_BOOL(tcache, ",")
 	OPT_WRITE_SSIZE_T(lg_tcache_max, ",")
+	OPT_WRITE_BOOL(thp, ",")
 	OPT_WRITE_BOOL(prof, ",")
 	OPT_WRITE_CHAR_P(prof_prefix, ",")
 	OPT_WRITE_BOOL_MUTABLE(prof_active, prof.active, ",")
 	OPT_WRITE_BOOL_MUTABLE(prof_thread_active_init, prof.thread_active_init,
 	    ",")
 	OPT_WRITE_SSIZE_T_MUTABLE(lg_prof_sample, prof.lg_sample, ",")
 	OPT_WRITE_BOOL(prof_accum, ",")
 	OPT_WRITE_SSIZE_T(lg_prof_interval, ",")
@@ -833,19 +843,21 @@ stats_general_print(void (*write_cb)(voi
 
 	if (json) {
 		unsigned nbins, nlruns, nhchunks, i;
 
 		CTL_GET("arenas.nbins", &nbins, unsigned);
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\"nbins\": %u,\n", nbins);
 
-		CTL_GET("arenas.nhbins", &uv, unsigned);
-		malloc_cprintf(write_cb, cbopaque,
-		    "\t\t\t\"nhbins\": %u,\n", uv);
+		if (config_tcache) {
+			CTL_GET("arenas.nhbins", &uv, unsigned);
+			malloc_cprintf(write_cb, cbopaque,
+			    "\t\t\t\"nhbins\": %u,\n", uv);
+		}
 
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\"bin\": [\n");
 		for (i = 0; i < nbins; i++) {
 			malloc_cprintf(write_cb, cbopaque,
 			    "\t\t\t\t{\n");
 
 			CTL_M2_GET("arenas.bin.0.size", i, &sv, size_t);
@@ -902,21 +914,21 @@ stats_general_print(void (*write_cb)(voi
 
 			malloc_cprintf(write_cb, cbopaque,
 			    "\t\t\t\t}%s\n", (i + 1 < nhchunks) ? "," : "");
 		}
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t]\n");
 
 		malloc_cprintf(write_cb, cbopaque,
-		    "\t\t},\n");
+		    "\t\t}%s\n", (config_prof || more) ? "," : "");
 	}
 
 	/* prof. */
-	if (json) {
+	if (config_prof && json) {
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\"prof\": {\n");
 
 		CTL_GET("prof.thread_active_init", &bv, bool);
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\"thread_active_init\": %s,\n", bv ? "true" :
 		    "false");
 
@@ -932,18 +944,17 @@ stats_general_print(void (*write_cb)(voi
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\"interval\": %"FMTu64",\n", u64v);
 
 		CTL_GET("prof.lg_sample", &ssv, ssize_t);
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t\t\t\"lg_sample\": %zd\n", ssv);
 
 		malloc_cprintf(write_cb, cbopaque,
-		    "\t\t}%s\n", (config_stats || merged || unmerged) ? "," :
-		    "");
+		    "\t\t}%s\n", more ? "," : "");
 	}
 }
 
 static void
 stats_print_helper(void (*write_cb)(void *, const char *), void *cbopaque,
     bool json, bool merged, bool unmerged, bool bins, bool large, bool huge)
 {
 	size_t *cactive;
@@ -1018,41 +1029,47 @@ stats_print_helper(void (*write_cb)(void
 				} else {
 					malloc_cprintf(write_cb, cbopaque,
 					    "\nMerged arenas stats:\n");
 				}
 				stats_arena_print(write_cb, cbopaque, json,
 				    narenas, bins, large, huge);
 				if (json) {
 					malloc_cprintf(write_cb, cbopaque,
-					    "\t\t\t}%s\n", (ninitialized > 1) ?
-					    "," : "");
+					    "\t\t\t}%s\n", unmerged ?  "," :
+					    "");
 				}
 			}
 
 			/* Unmerged stats. */
-			for (i = j = 0; i < narenas; i++) {
-				if (initialized[i]) {
-					if (json) {
-						j++;
-						malloc_cprintf(write_cb,
-						    cbopaque,
-						    "\t\t\t\"%u\": {\n", i);
-					} else {
-						malloc_cprintf(write_cb,
-						    cbopaque, "\narenas[%u]:\n",
-						    i);
-					}
-					stats_arena_print(write_cb, cbopaque,
-					    json, i, bins, large, huge);
-					if (json) {
-						malloc_cprintf(write_cb,
-						    cbopaque,
-						    "\t\t\t}%s\n", (j <
-						    ninitialized) ? "," : "");
+			if (unmerged) {
+				for (i = j = 0; i < narenas; i++) {
+					if (initialized[i]) {
+						if (json) {
+							j++;
+							malloc_cprintf(write_cb,
+							    cbopaque,
+							    "\t\t\t\"%u\": {\n",
+							    i);
+						} else {
+							malloc_cprintf(write_cb,
+							    cbopaque,
+							    "\narenas[%u]:\n",
+							    i);
+						}
+						stats_arena_print(write_cb,
+						    cbopaque, json, i, bins,
+						    large, huge);
+						if (json) {
+							malloc_cprintf(write_cb,
+							    cbopaque,
+							    "\t\t\t}%s\n", (j <
+							    ninitialized) ? ","
+							    : "");
+						}
 					}
 				}
 			}
 		}
 
 		if (json) {
 			malloc_cprintf(write_cb, cbopaque,
 			    "\t\t}\n");
@@ -1064,18 +1081,18 @@ void
 stats_print(void (*write_cb)(void *, const char *), void *cbopaque,
     const char *opts)
 {
 	int err;
 	uint64_t epoch;
 	size_t u64sz;
 	bool json = false;
 	bool general = true;
-	bool merged = true;
-	bool unmerged = true;
+	bool merged = config_stats;
+	bool unmerged = config_stats;
 	bool bins = true;
 	bool large = true;
 	bool huge = true;
 
 	/*
 	 * Refresh stats, in case mallctl() was called by the application.
 	 *
 	 * Check for OOM here, since refreshing the ctl cache can trigger
@@ -1132,18 +1149,20 @@ stats_print(void (*write_cb)(void *, con
 		malloc_cprintf(write_cb, cbopaque,
 		    "{\n"
 		    "\t\"jemalloc\": {\n");
 	} else {
 		malloc_cprintf(write_cb, cbopaque,
 		    "___ Begin jemalloc statistics ___\n");
 	}
 
-	if (general)
-		stats_general_print(write_cb, cbopaque, json, merged, unmerged);
+	if (general) {
+		bool more = (merged || unmerged);
+		stats_general_print(write_cb, cbopaque, json, more);
+	}
 	if (config_stats) {
 		stats_print_helper(write_cb, cbopaque, json, merged, unmerged,
 		    bins, large, huge);
 	}
 	if (json) {
 		malloc_cprintf(write_cb, cbopaque,
 		    "\t}\n"
 		    "}\n");
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/src/tcache.c
+++ b/memory/jemalloc/src/src/tcache.c
@@ -16,16 +16,19 @@ size_t			tcache_maxclass;
 tcaches_t		*tcaches;
 
 /* Index of first element within tcaches that has never been used. */
 static unsigned		tcaches_past;
 
 /* Head of singly linked list tracking available tcaches elements. */
 static tcaches_t	*tcaches_avail;
 
+/* Protects tcaches{,_past,_avail}. */
+static malloc_mutex_t	tcaches_mtx;
+
 /******************************************************************************/
 
 size_t
 tcache_salloc(tsdn_t *tsdn, const void *ptr)
 {
 
 	return (arena_salloc(tsdn, ptr, false));
 }
@@ -439,96 +442,136 @@ tcache_stats_merge(tsdn_t *tsdn, tcache_
 		malloc_large_stats_t *lstats = &arena->stats.lstats[i - NBINS];
 		tcache_bin_t *tbin = &tcache->tbins[i];
 		arena->stats.nrequests_large += tbin->tstats.nrequests;
 		lstats->nrequests += tbin->tstats.nrequests;
 		tbin->tstats.nrequests = 0;
 	}
 }
 
-bool
-tcaches_create(tsd_t *tsd, unsigned *r_ind)
-{
-	arena_t *arena;
-	tcache_t *tcache;
-	tcaches_t *elm;
+static bool
+tcaches_create_prep(tsd_t *tsd) {
+	bool err;
+
+	malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx);
 
 	if (tcaches == NULL) {
 		tcaches = base_alloc(tsd_tsdn(tsd), sizeof(tcache_t *) *
 		    (MALLOCX_TCACHE_MAX+1));
-		if (tcaches == NULL)
-			return (true);
+		if (tcaches == NULL) {
+			err = true;
+			goto label_return;
+		}
+	}
+
+	if (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX) {
+		err = true;
+		goto label_return;
 	}
 
-	if (tcaches_avail == NULL && tcaches_past > MALLOCX_TCACHE_MAX)
-		return (true);
+	err = false;
+label_return:
+	malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx);
+	return err;
+}
+
+bool
+tcaches_create(tsd_t *tsd, unsigned *r_ind) {
+	bool err;
+	arena_t *arena;
+	tcache_t *tcache;
+	tcaches_t *elm;
+
+	if (tcaches_create_prep(tsd)) {
+		err = true;
+		goto label_return;
+	}
+
 	arena = arena_ichoose(tsd, NULL);
-	if (unlikely(arena == NULL))
-		return (true);
+	if (unlikely(arena == NULL)) {
+		err = true;
+		goto label_return;
+	}
 	tcache = tcache_create(tsd_tsdn(tsd), arena);
-	if (tcache == NULL)
-		return (true);
+	if (tcache == NULL) {
+		err = true;
+		goto label_return;
+	}
 
+	malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx);
 	if (tcaches_avail != NULL) {
 		elm = tcaches_avail;
 		tcaches_avail = tcaches_avail->next;
 		elm->tcache = tcache;
 		*r_ind = (unsigned)(elm - tcaches);
 	} else {
 		elm = &tcaches[tcaches_past];
 		elm->tcache = tcache;
 		*r_ind = tcaches_past;
 		tcaches_past++;
 	}
+	malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx);
 
-	return (false);
+	err = false;
+label_return:
+	malloc_mutex_assert_not_owner(tsd_tsdn(tsd), &tcaches_mtx);
+	return err;
 }
 
 static void
-tcaches_elm_flush(tsd_t *tsd, tcaches_t *elm)
-{
+tcaches_elm_flush(tsd_t *tsd, tcaches_t *elm) {
+	malloc_mutex_assert_owner(tsd_tsdn(tsd), &tcaches_mtx);
 
-	if (elm->tcache == NULL)
+	if (elm->tcache == NULL) {
 		return;
+	}
 	tcache_destroy(tsd, elm->tcache);
 	elm->tcache = NULL;
 }
 
 void
-tcaches_flush(tsd_t *tsd, unsigned ind)
-{
-
+tcaches_flush(tsd_t *tsd, unsigned ind) {
+	malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx);
 	tcaches_elm_flush(tsd, &tcaches[ind]);
+	malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx);
 }
 
 void
-tcaches_destroy(tsd_t *tsd, unsigned ind)
-{
-	tcaches_t *elm = &tcaches[ind];
+tcaches_destroy(tsd_t *tsd, unsigned ind) {
+	tcaches_t *elm;
+
+	malloc_mutex_lock(tsd_tsdn(tsd), &tcaches_mtx);
+	elm = &tcaches[ind];
 	tcaches_elm_flush(tsd, elm);
 	elm->next = tcaches_avail;
 	tcaches_avail = elm;
+	malloc_mutex_unlock(tsd_tsdn(tsd), &tcaches_mtx);
 }
 
 bool
-tcache_boot(tsdn_t *tsdn)
-{
+tcache_boot(tsdn_t *tsdn) {
 	unsigned i;
 
+	cassert(config_tcache);
+
 	/*
 	 * If necessary, clamp opt_lg_tcache_max, now that large_maxclass is
 	 * known.
 	 */
 	if (opt_lg_tcache_max < 0 || (ZU(1) << opt_lg_tcache_max) < SMALL_MAXCLASS)
 		tcache_maxclass = SMALL_MAXCLASS;
 	else if ((ZU(1) << opt_lg_tcache_max) > large_maxclass)
 		tcache_maxclass = large_maxclass;
 	else
 		tcache_maxclass = (ZU(1) << opt_lg_tcache_max);
 
+	if (malloc_mutex_init(&tcaches_mtx, "tcaches", WITNESS_RANK_TCACHES)) {
+		return true;
+	}
+
 	nhbins = size2index(tcache_maxclass) + 1;
 
 	/* Initialize tcache_bin_info. */
 	tcache_bin_info = (tcache_bin_info_t *)base_alloc(tsdn, nhbins *
 	    sizeof(tcache_bin_info_t));
 	if (tcache_bin_info == NULL)
 		return (true);
 	stack_nelms = 0;
@@ -548,8 +591,29 @@ tcache_boot(tsdn_t *tsdn)
 	}
 	for (; i < nhbins; i++) {
 		tcache_bin_info[i].ncached_max = TCACHE_NSLOTS_LARGE;
 		stack_nelms += tcache_bin_info[i].ncached_max;
 	}
 
 	return (false);
 }
+
+void
+tcache_prefork(tsdn_t *tsdn) {
+	if (!config_prof && opt_tcache) {
+		malloc_mutex_prefork(tsdn, &tcaches_mtx);
+	}
+}
+
+void
+tcache_postfork_parent(tsdn_t *tsdn) {
+	if (!config_prof && opt_tcache) {
+		malloc_mutex_postfork_parent(tsdn, &tcaches_mtx);
+	}
+}
+
+void
+tcache_postfork_child(tsdn_t *tsdn) {
+	if (!config_prof && opt_tcache) {
+		malloc_mutex_postfork_child(tsdn, &tcaches_mtx);
+	}
+}
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/src/witness.c
+++ b/memory/jemalloc/src/src/witness.c
@@ -66,36 +66,36 @@ witness_not_owner_error(const witness_t 
 #ifdef JEMALLOC_JET
 #undef witness_not_owner_error
 #define	witness_not_owner_error JEMALLOC_N(witness_not_owner_error)
 witness_not_owner_error_t *witness_not_owner_error =
     JEMALLOC_N(n_witness_not_owner_error);
 #endif
 
 #ifdef JEMALLOC_JET
-#undef witness_lockless_error
-#define	witness_lockless_error JEMALLOC_N(n_witness_lockless_error)
+#undef witness_depth_error
+#define witness_depth_error JEMALLOC_N(n_witness_depth_error)
 #endif
 void
-witness_lockless_error(const witness_list_t *witnesses)
-{
+witness_depth_error(const witness_list_t *witnesses,
+    witness_rank_t rank_inclusive, unsigned depth) {
 	witness_t *w;
 
-	malloc_printf("<jemalloc>: Should not own any locks:");
+	malloc_printf("<jemalloc>: Should own %u lock%s of rank >= %u:", depth,
+	    (depth != 1) ?  "s" : "", rank_inclusive);
 	ql_foreach(w, witnesses, link) {
 		malloc_printf(" %s(%u)", w->name, w->rank);
 	}
 	malloc_printf("\n");
 	abort();
 }
 #ifdef JEMALLOC_JET
-#undef witness_lockless_error
-#define	witness_lockless_error JEMALLOC_N(witness_lockless_error)
-witness_lockless_error_t *witness_lockless_error =
-    JEMALLOC_N(n_witness_lockless_error);
+#undef witness_depth_error
+#define witness_depth_error JEMALLOC_N(witness_depth_error)
+witness_depth_error_t *witness_depth_error = JEMALLOC_N(n_witness_depth_error);
 #endif
 
 void
 witnesses_cleanup(tsd_t *tsd)
 {
 
 	witness_assert_lockless(tsd_tsdn(tsd));
 
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/integration/chunk.c
+++ b/memory/jemalloc/src/test/integration/chunk.c
@@ -1,14 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_FILL
-const char *malloc_conf = "junk:false";
-#endif
-
 static chunk_hooks_t orig_hooks;
 static chunk_hooks_t old_hooks;
 
 static bool do_dalloc = true;
 static bool do_decommit;
 
 static bool did_alloc;
 static bool did_dalloc;
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/integration/chunk.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="junk:false"
+fi
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/integration/mallocx.c
+++ b/memory/jemalloc/src/test/integration/mallocx.c
@@ -1,14 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_FILL
-const char *malloc_conf = "junk:false";
-#endif
-
 static unsigned
 get_nsizes_impl(const char *cmd)
 {
 	unsigned ret;
 	size_t z;
 
 	z = sizeof(unsigned);
 	assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/integration/mallocx.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="junk:false"
+fi
old mode 100755
new mode 100644
old mode 100755
new mode 100644
old mode 100755
new mode 100644
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/integration/xallocx.c
+++ b/memory/jemalloc/src/test/integration/xallocx.c
@@ -1,14 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_FILL
-const char *malloc_conf = "junk:false";
-#endif
-
 /*
  * Use a separate arena for xallocx() extension/contraction tests so that
  * internal allocation e.g. by heap profiling can't interpose allocations where
  * xallocx() would ordinarily be able to extend.
  */
 static unsigned
 arena_ind(void)
 {
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/integration/xallocx.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="junk:false"
+fi
--- a/memory/jemalloc/src/test/test.sh.in
+++ b/memory/jemalloc/src/test/test.sh.in
@@ -6,30 +6,57 @@ case @abi@ in
     ;;
   pecoff)
     export PATH="${PATH}:@objroot@lib"
     ;;
   *)
     ;;
 esac
 
+# Make a copy of the @JEMALLOC_CPREFIX@MALLOC_CONF passed in to this script, so
+# it can be repeatedly concatenated with per test settings.
+export MALLOC_CONF_ALL=${@JEMALLOC_CPREFIX@MALLOC_CONF}
+# Concatenate the individual test's MALLOC_CONF and MALLOC_CONF_ALL.
+export_malloc_conf() {
+  if [ "x${MALLOC_CONF}" != "x" -a "x${MALLOC_CONF_ALL}" != "x" ] ; then
+    export @JEMALLOC_CPREFIX@MALLOC_CONF="${MALLOC_CONF},${MALLOC_CONF_ALL}"
+  else
+    export @JEMALLOC_CPREFIX@MALLOC_CONF="${MALLOC_CONF}${MALLOC_CONF_ALL}"
+  fi
+}
+
 # Corresponds to test_status_t.
 pass_code=0
 skip_code=1
 fail_code=2
 
 pass_count=0
 skip_count=0
 fail_count=0
 for t in $@; do
   if [ $pass_count -ne 0 -o $skip_count -ne 0 -o $fail_count != 0 ] ; then
     echo
   fi
   echo "=== ${t} ==="
-  ${t}@exe@ @abs_srcroot@ @abs_objroot@
+  if [ -e "@srcroot@${t}.sh" ] ; then
+    # Source the shell script corresponding to the test in a subshell and
+    # execute the test.  This allows the shell script to set MALLOC_CONF, which
+    # is then used to set @JEMALLOC_CPREFIX@MALLOC_CONF (thus allowing the
+    # per test shell script to ignore the @JEMALLOC_CPREFIX@ detail).
+    $(enable_fill=@enable_fill@ \
+      enable_prof=@enable_prof@ \
+      enable_tcache=@enable_tcache@ \
+      . @srcroot@${t}.sh && \
+      export_malloc_conf && \
+      ${t}@exe@ @abs_srcroot@ @abs_objroot@)
+  else
+    $(export MALLOC_CONF= && \
+      export_malloc_conf &&
+      ${t}@exe@ @abs_srcroot@ @abs_objroot@)
+  fi
   result_code=$?
   case ${result_code} in
     ${pass_code})
       pass_count=$((pass_count+1))
       ;;
     ${skip_code})
       skip_count=$((skip_count+1))
       ;;
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/arena_reset.c
+++ b/memory/jemalloc/src/test/unit/arena_reset.c
@@ -1,14 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_PROF
-const char *malloc_conf = "prof:true,lg_prof_sample:0";
-#endif
-
 static unsigned
 get_nsizes_impl(const char *cmd)
 {
 	unsigned ret;
 	size_t z;
 
 	z = sizeof(unsigned);
 	assert_d_eq(mallctl(cmd, (void *)&ret, &z, NULL, 0), 0,
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/arena_reset.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,lg_prof_sample:0"
+fi
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/decay.c
+++ b/memory/jemalloc/src/test/unit/decay.c
@@ -1,12 +1,10 @@
 #include "test/jemalloc_test.h"
 
-const char *malloc_conf = "purge:decay,decay_time:1";
-
 static nstime_monotonic_t *nstime_monotonic_orig;
 static nstime_update_t *nstime_update_orig;
 
 static unsigned nupdates_mock;
 static nstime_t time_mock;
 static bool monotonic_mock;
 
 static bool
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/decay.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+export MALLOC_CONF="purge:decay,decay_time:1"
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/extent_quantize.c
@@ -0,0 +1,98 @@
+#include "test/jemalloc_test.h"
+
+TEST_BEGIN(test_huge_extent_size) {
+	unsigned nhchunks, i;
+	size_t sz, extent_size_prev, ceil_prev;
+	size_t mib[4];
+	size_t miblen = sizeof(mib) / sizeof(size_t);
+
+	/*
+	 * Iterate over all huge size classes, get their extent sizes, and
+	 * verify that the quantized size is the same as the extent size.
+	 */
+
+	sz = sizeof(unsigned);
+	assert_d_eq(mallctl("arenas.nhchunks", (void *)&nhchunks, &sz, NULL,
+	    0), 0, "Unexpected mallctl failure");
+
+	assert_d_eq(mallctlnametomib("arenas.hchunk.0.size", mib, &miblen), 0,
+	    "Unexpected mallctlnametomib failure");
+	for (i = 0; i < nhchunks; i++) {
+		size_t extent_size, floor, ceil;
+
+
+		mib[2] = i;
+		sz = sizeof(size_t);
+		assert_d_eq(mallctlbymib(mib, miblen, (void *)&extent_size,
+		    &sz, NULL, 0), 0, "Unexpected mallctlbymib failure");
+		floor = extent_size_quantize_floor(extent_size);
+		ceil = extent_size_quantize_ceil(extent_size);
+
+		assert_zu_eq(extent_size, floor,
+		    "Extent quantization should be a no-op for precise size "
+		    "(extent_size=%zu)", extent_size);
+		assert_zu_eq(extent_size, ceil,
+		    "Extent quantization should be a no-op for precise size "
+		    "(extent_size=%zu)", extent_size);
+
+		if (i > 0) {
+			assert_zu_eq(extent_size_prev,
+			    extent_size_quantize_floor(extent_size - PAGE),
+			    "Floor should be a precise size");
+			if (extent_size_prev < ceil_prev) {
+				assert_zu_eq(ceil_prev, extent_size,
+				    "Ceiling should be a precise size "
+				    "(extent_size_prev=%zu, ceil_prev=%zu, "
+				    "extent_size=%zu)", extent_size_prev,
+				    ceil_prev, extent_size);
+			}
+		}
+		if (i + 1 < nhchunks) {
+			extent_size_prev = floor;
+			ceil_prev = extent_size_quantize_ceil(extent_size +
+			    PAGE);
+		}
+	}
+}
+TEST_END
+
+TEST_BEGIN(test_monotonic) {
+#define SZ_MAX	ZU(4 * 1024 * 1024)
+	unsigned i;
+	size_t floor_prev, ceil_prev;
+
+	floor_prev = 0;
+	ceil_prev = 0;
+	for (i = 1; i <= SZ_MAX >> LG_PAGE; i++) {
+		size_t extent_size, floor, ceil;
+
+		extent_size = i << LG_PAGE;
+		floor = extent_size_quantize_floor(extent_size);
+		ceil = extent_size_quantize_ceil(extent_size);
+
+		assert_zu_le(floor, extent_size,
+		    "Floor should be <= (floor=%zu, extent_size=%zu, ceil=%zu)",
+		    floor, extent_size, ceil);
+		assert_zu_ge(ceil, extent_size,
+		    "Ceiling should be >= (floor=%zu, extent_size=%zu, "
+		    "ceil=%zu)", floor, extent_size, ceil);
+
+		assert_zu_le(floor_prev, floor, "Floor should be monotonic "
+		    "(floor_prev=%zu, floor=%zu, extent_size=%zu, ceil=%zu)",
+		    floor_prev, floor, extent_size, ceil);
+		assert_zu_le(ceil_prev, ceil, "Ceiling should be monotonic "
+		    "(floor=%zu, extent_size=%zu, ceil_prev=%zu, ceil=%zu)",
+		    floor, extent_size, ceil_prev, ceil);
+
+		floor_prev = floor;
+		ceil_prev = ceil;
+	}
+}
+TEST_END
+
+int
+main(void) {
+	return test(
+	    test_huge_extent_size,
+	    test_monotonic);
+}
--- a/memory/jemalloc/src/test/unit/junk.c
+++ b/memory/jemalloc/src/test/unit/junk.c
@@ -1,18 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_FILL
-#  ifndef JEMALLOC_TEST_JUNK_OPT
-#    define JEMALLOC_TEST_JUNK_OPT "junk:true"
-#  endif
-const char *malloc_conf =
-    "abort:false,zero:false,redzone:true,quarantine:0," JEMALLOC_TEST_JUNK_OPT;
-#endif
-
 static arena_dalloc_junk_small_t *arena_dalloc_junk_small_orig;
 static arena_dalloc_junk_large_t *arena_dalloc_junk_large_orig;
 static huge_dalloc_junk_t *huge_dalloc_junk_orig;
 static void *watch_for_junking;
 static bool saw_junking;
 
 static void
 watch_junking(void *p)
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/junk.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="abort:false,zero:false,redzone:true,quarantine:0,junk:true"
+fi
--- a/memory/jemalloc/src/test/unit/junk_alloc.c
+++ b/memory/jemalloc/src/test/unit/junk_alloc.c
@@ -1,3 +1,1 @@
-#define	JEMALLOC_TEST_JUNK_OPT "junk:alloc"
 #include "junk.c"
-#undef JEMALLOC_TEST_JUNK_OPT
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/junk_alloc.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="abort:false,zero:false,redzone:true,quarantine:0,junk:alloc"
+fi
--- a/memory/jemalloc/src/test/unit/junk_free.c
+++ b/memory/jemalloc/src/test/unit/junk_free.c
@@ -1,3 +1,1 @@
-#define	JEMALLOC_TEST_JUNK_OPT "junk:free"
 #include "junk.c"
-#undef JEMALLOC_TEST_JUNK_OPT
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/junk_free.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="abort:false,zero:false,redzone:true,quarantine:0,junk:free"
+fi
--- a/memory/jemalloc/src/test/unit/lg_chunk.c
+++ b/memory/jemalloc/src/test/unit/lg_chunk.c
@@ -1,17 +1,10 @@
 #include "test/jemalloc_test.h"
 
-/*
- * Make sure that opt.lg_chunk clamping is sufficient.  In practice, this test
- * program will fail a debug assertion during initialization and abort (rather
- * than the test soft-failing) if clamping is insufficient.
- */
-const char *malloc_conf = "lg_chunk:0";
-
 TEST_BEGIN(test_lg_chunk_clamp)
 {
 	void *p;
 
 	p = mallocx(1, 0);
 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
 	dallocx(p, 0);
 }
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/lg_chunk.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# Make sure that opt.lg_chunk clamping is sufficient.  In practice, this test
+# program will fail a debug assertion during initialization and abort (rather
+# than the test soft-failing) if clamping is insufficient.
+export MALLOC_CONF="lg_chunk:0"
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/mallctl.c
+++ b/memory/jemalloc/src/test/unit/mallctl.c
@@ -137,16 +137,17 @@ TEST_BEGIN(test_mallctl_config)
 	TEST_MALLCTL_CONFIG(lazy_lock, bool);
 	TEST_MALLCTL_CONFIG(malloc_conf, const char *);
 	TEST_MALLCTL_CONFIG(munmap, bool);
 	TEST_MALLCTL_CONFIG(prof, bool);
 	TEST_MALLCTL_CONFIG(prof_libgcc, bool);
 	TEST_MALLCTL_CONFIG(prof_libunwind, bool);
 	TEST_MALLCTL_CONFIG(stats, bool);
 	TEST_MALLCTL_CONFIG(tcache, bool);
+	TEST_MALLCTL_CONFIG(thp, bool);
 	TEST_MALLCTL_CONFIG(tls, bool);
 	TEST_MALLCTL_CONFIG(utrace, bool);
 	TEST_MALLCTL_CONFIG(valgrind, bool);
 	TEST_MALLCTL_CONFIG(xmalloc, bool);
 
 #undef TEST_MALLCTL_CONFIG
 }
 TEST_END
@@ -177,16 +178,17 @@ TEST_BEGIN(test_mallctl_opt)
 	TEST_MALLCTL_OPT(const char *, junk, fill);
 	TEST_MALLCTL_OPT(size_t, quarantine, fill);
 	TEST_MALLCTL_OPT(bool, redzone, fill);
 	TEST_MALLCTL_OPT(bool, zero, fill);
 	TEST_MALLCTL_OPT(bool, utrace, utrace);
 	TEST_MALLCTL_OPT(bool, xmalloc, xmalloc);
 	TEST_MALLCTL_OPT(bool, tcache, tcache);
 	TEST_MALLCTL_OPT(size_t, lg_tcache_max, tcache);
+	TEST_MALLCTL_OPT(bool, thp, thp);
 	TEST_MALLCTL_OPT(bool, prof, prof);
 	TEST_MALLCTL_OPT(const char *, prof_prefix, prof);
 	TEST_MALLCTL_OPT(bool, prof_active, prof);
 	TEST_MALLCTL_OPT(ssize_t, lg_prof_sample, prof);
 	TEST_MALLCTL_OPT(bool, prof_accum, prof);
 	TEST_MALLCTL_OPT(ssize_t, lg_prof_interval, prof);
 	TEST_MALLCTL_OPT(bool, prof_gdump, prof);
 	TEST_MALLCTL_OPT(bool, prof_final, prof);
--- a/memory/jemalloc/src/test/unit/pack.c
+++ b/memory/jemalloc/src/test/unit/pack.c
@@ -1,18 +1,10 @@
 #include "test/jemalloc_test.h"
 
-const char *malloc_conf =
-    /* Use smallest possible chunk size. */
-    "lg_chunk:0"
-    /* Immediately purge to minimize fragmentation. */
-    ",lg_dirty_mult:-1"
-    ",decay_time:-1"
-    ;
-
 /*
  * Size class that is a divisor of the page size, ideally 4+ regions per run.
  */
 #if LG_PAGE <= 14
 #define	SZ	(ZU(1) << (LG_PAGE - 2))
 #else
 #define	SZ	4096
 #endif
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/pack.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# Use smallest possible chunk size.  Immediately purge to minimize
+# fragmentation.
+export MALLOC_CONF="lg_chunk:0,lg_dirty_mult:-1,decay_time:-1"
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/prof_accum.c
+++ b/memory/jemalloc/src/test/unit/prof_accum.c
@@ -1,20 +1,15 @@
 #include "test/jemalloc_test.h"
 
 #define	NTHREADS		4
 #define	NALLOCS_PER_THREAD	50
 #define	DUMP_INTERVAL		1
 #define	BT_COUNT_CHECK_INTERVAL	5
 
-#ifdef JEMALLOC_PROF
-const char *malloc_conf =
-    "prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0";
-#endif
-
 static int
 prof_dump_open_intercept(bool propagate_err, const char *filename)
 {
 	int fd;
 
 	fd = open("/dev/null", O_WRONLY);
 	assert_d_ne(fd, -1, "Unexpected open() failure");
 
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/prof_accum.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0"
+fi
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/prof_active.c
+++ b/memory/jemalloc/src/test/unit/prof_active.c
@@ -1,15 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_PROF
-const char *malloc_conf =
-    "prof:true,prof_thread_active_init:false,lg_prof_sample:0";
-#endif
-
 static void
 mallctl_bool_get(const char *name, bool expected, const char *func, int line)
 {
 	bool old;
 	size_t sz;
 
 	sz = sizeof(old);
 	assert_d_eq(mallctl(name, (void *)&old, &sz, NULL, 0), 0,
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/prof_active.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,prof_thread_active_init:false,lg_prof_sample:0"
+fi
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/prof_gdump.c
+++ b/memory/jemalloc/src/test/unit/prof_gdump.c
@@ -1,14 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_PROF
-const char *malloc_conf = "prof:true,prof_active:false,prof_gdump:true";
-#endif
-
 static bool did_prof_dump_open;
 
 static int
 prof_dump_open_intercept(bool propagate_err, const char *filename)
 {
 	int fd;
 
 	did_prof_dump_open = true;
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/prof_gdump.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,prof_active:false,prof_gdump:true"
+fi
+
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/prof_idump.c
+++ b/memory/jemalloc/src/test/unit/prof_idump.c
@@ -1,16 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_PROF
-const char *malloc_conf =
-    "prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0,"
-    "lg_prof_interval:0";
-#endif
-
 static bool did_prof_dump_open;
 
 static int
 prof_dump_open_intercept(bool propagate_err, const char *filename)
 {
 	int fd;
 
 	did_prof_dump_open = true;
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/prof_idump.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,prof_accum:true,prof_active:false,lg_prof_sample:0,lg_prof_interval:0"
+fi
+
+
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/prof_reset.c
+++ b/memory/jemalloc/src/test/unit/prof_reset.c
@@ -1,15 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_PROF
-const char *malloc_conf =
-    "prof:true,prof_active:false,lg_prof_sample:0";
-#endif
-
 static int
 prof_dump_open_intercept(bool propagate_err, const char *filename)
 {
 	int fd;
 
 	fd = open("/dev/null", O_WRONLY);
 	assert_d_ne(fd, -1, "Unexpected open() failure");
 
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/prof_reset.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,prof_active:false,lg_prof_sample:0"
+fi
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/prof_tctx.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,lg_prof_sample:0"
+fi
old mode 100755
new mode 100644
--- a/memory/jemalloc/src/test/unit/prof_thread_name.c
+++ b/memory/jemalloc/src/test/unit/prof_thread_name.c
@@ -1,14 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_PROF
-const char *malloc_conf = "prof:true,prof_active:false";
-#endif
-
 static void
 mallctl_thread_name_get_impl(const char *thread_name_expected, const char *func,
     int line)
 {
 	const char *thread_name_old;
 	size_t sz;
 
 	sz = sizeof(thread_name_old);
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/prof_thread_name.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_prof}" = "x1" ] ; then
+  export MALLOC_CONF="prof:true,prof_active:false"
+fi
--- a/memory/jemalloc/src/test/unit/quarantine.c
+++ b/memory/jemalloc/src/test/unit/quarantine.c
@@ -1,18 +1,12 @@
 #include "test/jemalloc_test.h"
 
+/* Keep in sync with definition in quarantine.sh. */
 #define	QUARANTINE_SIZE		8192
-#define	STRINGIFY_HELPER(x)	#x
-#define	STRINGIFY(x)		STRINGIFY_HELPER(x)
-
-#ifdef JEMALLOC_FILL
-const char *malloc_conf = "abort:false,junk:true,redzone:true,quarantine:"
-    STRINGIFY(QUARANTINE_SIZE);
-#endif
 
 void
 quarantine_clear(void)
 {
 	void *p;
 
 	p = mallocx(QUARANTINE_SIZE*2, 0);
 	assert_ptr_not_null(p, "Unexpected mallocx() failure");
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/quarantine.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+# Keep in sync with definition in quarantine.c.
+export QUARANTINE_SIZE=8192
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="abort:false,junk:true,redzone:true,quarantine:${QUARANTINE_SIZE}"
+fi
old mode 100755
new mode 100644
old mode 100755
new mode 100644
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/stats_print.c
@@ -0,0 +1,1005 @@
+#include "test/jemalloc_test.h"
+
+typedef enum {
+	TOKEN_TYPE_NONE,
+	TOKEN_TYPE_ERROR,
+	TOKEN_TYPE_EOI,
+	TOKEN_TYPE_NULL,
+	TOKEN_TYPE_FALSE,
+	TOKEN_TYPE_TRUE,
+	TOKEN_TYPE_LBRACKET,
+	TOKEN_TYPE_RBRACKET,
+	TOKEN_TYPE_LBRACE,
+	TOKEN_TYPE_RBRACE,
+	TOKEN_TYPE_COLON,
+	TOKEN_TYPE_COMMA,
+	TOKEN_TYPE_STRING,
+	TOKEN_TYPE_NUMBER
+} token_type_t;
+
+typedef struct parser_s parser_t;
+typedef struct {
+	parser_t	*parser;
+	token_type_t	token_type;
+	size_t		pos;
+	size_t		len;
+	size_t		line;
+	size_t		col;
+} token_t;
+
+struct parser_s {
+	bool verbose;
+	char	*buf; /* '\0'-terminated. */
+	size_t	len; /* Number of characters preceding '\0' in buf. */
+	size_t	pos;
+	size_t	line;
+	size_t	col;
+	token_t	token;
+};
+
+static void
+token_init(token_t *token, parser_t *parser, token_type_t token_type,
+    size_t pos, size_t len, size_t line, size_t col)
+{
+	token->parser = parser;
+	token->token_type = token_type;
+	token->pos = pos;
+	token->len = len;
+	token->line = line;
+	token->col = col;
+}
+
+static void
+token_error(token_t *token)
+{
+	if (!token->parser->verbose) {
+		return;
+	}
+	switch (token->token_type) {
+	case TOKEN_TYPE_NONE:
+		not_reached();
+	case TOKEN_TYPE_ERROR:
+		malloc_printf("%zu:%zu: Unexpected character in token: ",
+		    token->line, token->col);
+		break;
+	default:
+		malloc_printf("%zu:%zu: Unexpected token: ", token->line,
+		    token->col);
+		break;
+	}
+	{
+		UNUSED ssize_t err = write(STDERR_FILENO,
+		    &token->parser->buf[token->pos], token->len);
+	}
+	malloc_printf("\n");
+}
+
+static void
+parser_init(parser_t *parser, bool verbose)
+{
+	parser->verbose = verbose;
+	parser->buf = NULL;
+	parser->len = 0;
+	parser->pos = 0;
+	parser->line = 1;
+	parser->col = 0;
+}
+
+static void
+parser_fini(parser_t *parser)
+{
+	if (parser->buf != NULL) {
+		dallocx(parser->buf, MALLOCX_TCACHE_NONE);
+	}
+}
+
+static bool
+parser_append(parser_t *parser, const char *str)
+{
+	size_t len = strlen(str);
+	char *buf = (parser->buf == NULL) ? mallocx(len + 1,
+	    MALLOCX_TCACHE_NONE) : rallocx(parser->buf, parser->len + len + 1,
+	    MALLOCX_TCACHE_NONE);
+	if (buf == NULL) {
+		return true;
+	}
+	memcpy(&buf[parser->len], str, len + 1);
+	parser->buf = buf;
+	parser->len += len;
+	return false;
+}
+
+static bool
+parser_tokenize(parser_t *parser)
+{
+	enum {
+		STATE_START,
+		STATE_EOI,
+		STATE_N, STATE_NU, STATE_NUL, STATE_NULL,
+		STATE_F, STATE_FA, STATE_FAL, STATE_FALS, STATE_FALSE,
+		STATE_T, STATE_TR, STATE_TRU, STATE_TRUE,
+		STATE_LBRACKET,
+		STATE_RBRACKET,
+		STATE_LBRACE,
+		STATE_RBRACE,
+		STATE_COLON,
+		STATE_COMMA,
+		STATE_CHARS,
+		STATE_CHAR_ESCAPE,
+		STATE_CHAR_U, STATE_CHAR_UD, STATE_CHAR_UDD, STATE_CHAR_UDDD,
+		STATE_STRING,
+		STATE_MINUS,
+		STATE_LEADING_ZERO,
+		STATE_DIGITS,
+		STATE_DECIMAL,
+		STATE_FRAC_DIGITS,
+		STATE_EXP,
+		STATE_EXP_SIGN,
+		STATE_EXP_DIGITS,
+		STATE_ACCEPT
+	} state = STATE_START;
+	size_t token_pos JEMALLOC_CC_SILENCE_INIT(0);
+	size_t token_line JEMALLOC_CC_SILENCE_INIT(1);
+	size_t token_col JEMALLOC_CC_SILENCE_INIT(0);
+
+	assert_zu_le(parser->pos, parser->len,
+	    "Position is past end of buffer");
+
+	while (state != STATE_ACCEPT) {
+		char c = parser->buf[parser->pos];
+
+		switch (state) {
+		case STATE_START:
+			token_pos = parser->pos;
+			token_line = parser->line;
+			token_col = parser->col;
+			switch (c) {
+			case ' ': case '\b': case '\n': case '\r': case '\t':
+				break;
+			case '\0':
+				state = STATE_EOI;
+				break;
+			case 'n':
+				state = STATE_N;
+				break;
+			case 'f':
+				state = STATE_F;
+				break;
+			case 't':
+				state = STATE_T;
+				break;
+			case '[':
+				state = STATE_LBRACKET;
+				break;
+			case ']':
+				state = STATE_RBRACKET;
+				break;
+			case '{':
+				state = STATE_LBRACE;
+				break;
+			case '}':
+				state = STATE_RBRACE;
+				break;
+			case ':':
+				state = STATE_COLON;
+				break;
+			case ',':
+				state = STATE_COMMA;
+				break;
+			case '"':
+				state = STATE_CHARS;
+				break;
+			case '-':
+				state = STATE_MINUS;
+				break;
+			case '0':
+				state = STATE_LEADING_ZERO;
+				break;
+			case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				state = STATE_DIGITS;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_EOI:
+			token_init(&parser->token, parser,
+			    TOKEN_TYPE_EOI, token_pos, parser->pos -
+			    token_pos, token_line, token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_N:
+			switch (c) {
+			case 'u':
+				state = STATE_NU;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_NU:
+			switch (c) {
+			case 'l':
+				state = STATE_NUL;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_NUL:
+			switch (c) {
+			case 'l':
+				state = STATE_NULL;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_NULL:
+			switch (c) {
+			case ' ': case '\b': case '\n': case '\r': case '\t':
+			case '\0':
+			case '[': case ']': case '{': case '}': case ':':
+			case ',':
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			token_init(&parser->token, parser, TOKEN_TYPE_NULL,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_F:
+			switch (c) {
+			case 'a':
+				state = STATE_FA;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_FA:
+			switch (c) {
+			case 'l':
+				state = STATE_FAL;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_FAL:
+			switch (c) {
+			case 's':
+				state = STATE_FALS;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_FALS:
+			switch (c) {
+			case 'e':
+				state = STATE_FALSE;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_FALSE:
+			switch (c) {
+			case ' ': case '\b': case '\n': case '\r': case '\t':
+			case '\0':
+			case '[': case ']': case '{': case '}': case ':':
+			case ',':
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			token_init(&parser->token, parser,
+			    TOKEN_TYPE_FALSE, token_pos, parser->pos -
+			    token_pos, token_line, token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_T:
+			switch (c) {
+			case 'r':
+				state = STATE_TR;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_TR:
+			switch (c) {
+			case 'u':
+				state = STATE_TRU;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_TRU:
+			switch (c) {
+			case 'e':
+				state = STATE_TRUE;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_TRUE:
+			switch (c) {
+			case ' ': case '\b': case '\n': case '\r': case '\t':
+			case '\0':
+			case '[': case ']': case '{': case '}': case ':':
+			case ',':
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			token_init(&parser->token, parser, TOKEN_TYPE_TRUE,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_LBRACKET:
+			token_init(&parser->token, parser, TOKEN_TYPE_LBRACKET,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_RBRACKET:
+			token_init(&parser->token, parser, TOKEN_TYPE_RBRACKET,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_LBRACE:
+			token_init(&parser->token, parser, TOKEN_TYPE_LBRACE,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_RBRACE:
+			token_init(&parser->token, parser, TOKEN_TYPE_RBRACE,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_COLON:
+			token_init(&parser->token, parser, TOKEN_TYPE_COLON,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_COMMA:
+			token_init(&parser->token, parser, TOKEN_TYPE_COMMA,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_CHARS:
+			switch (c) {
+			case '\\':
+				state = STATE_CHAR_ESCAPE;
+				break;
+			case '"':
+				state = STATE_STRING;
+				break;
+			case 0x00: case 0x01: case 0x02: case 0x03: case 0x04:
+			case 0x05: case 0x06: case 0x07: case 0x08: case 0x09:
+			case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e:
+			case 0x0f: case 0x10: case 0x11: case 0x12: case 0x13:
+			case 0x14: case 0x15: case 0x16: case 0x17: case 0x18:
+			case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d:
+			case 0x1e: case 0x1f:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			default:
+				break;
+			}
+			break;
+		case STATE_CHAR_ESCAPE:
+			switch (c) {
+			case '"': case '\\': case '/': case 'b': case 'n':
+			case 'r': case 't':
+				state = STATE_CHARS;
+				break;
+			case 'u':
+				state = STATE_CHAR_U;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_CHAR_U:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+			case 'a': case 'b': case 'c': case 'd': case 'e':
+			case 'f':
+			case 'A': case 'B': case 'C': case 'D': case 'E':
+			case 'F':
+				state = STATE_CHAR_UD;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_CHAR_UD:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+			case 'a': case 'b': case 'c': case 'd': case 'e':
+			case 'f':
+			case 'A': case 'B': case 'C': case 'D': case 'E':
+			case 'F':
+				state = STATE_CHAR_UDD;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_CHAR_UDD:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+			case 'a': case 'b': case 'c': case 'd': case 'e':
+			case 'f':
+			case 'A': case 'B': case 'C': case 'D': case 'E':
+			case 'F':
+				state = STATE_CHAR_UDDD;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_CHAR_UDDD:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+			case 'a': case 'b': case 'c': case 'd': case 'e':
+			case 'f':
+			case 'A': case 'B': case 'C': case 'D': case 'E':
+			case 'F':
+				state = STATE_CHARS;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_STRING:
+			token_init(&parser->token, parser, TOKEN_TYPE_STRING,
+			    token_pos, parser->pos - token_pos, token_line,
+			    token_col);
+			state = STATE_ACCEPT;
+			break;
+		case STATE_MINUS:
+			switch (c) {
+			case '0':
+				state = STATE_LEADING_ZERO;
+				break;
+			case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				state = STATE_DIGITS;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_LEADING_ZERO:
+			switch (c) {
+			case '.':
+				state = STATE_DECIMAL;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
+				    token_pos, token_line, token_col);
+				state = STATE_ACCEPT;
+				break;
+			}
+			break;
+		case STATE_DIGITS:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				break;
+			case '.':
+				state = STATE_DECIMAL;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
+				    token_pos, token_line, token_col);
+				state = STATE_ACCEPT;
+				break;
+			}
+			break;
+		case STATE_DECIMAL:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				state = STATE_FRAC_DIGITS;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_FRAC_DIGITS:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				break;
+			case 'e': case 'E':
+				state = STATE_EXP;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
+				    token_pos, token_line, token_col);
+				state = STATE_ACCEPT;
+				break;
+			}
+			break;
+		case STATE_EXP:
+			switch (c) {
+			case '-': case '+':
+				state = STATE_EXP_SIGN;
+				break;
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				state = STATE_EXP_DIGITS;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_EXP_SIGN:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				state = STATE_EXP_DIGITS;
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_ERROR, token_pos, parser->pos + 1
+				    - token_pos, token_line, token_col);
+				return true;
+			}
+			break;
+		case STATE_EXP_DIGITS:
+			switch (c) {
+			case '0': case '1': case '2': case '3': case '4':
+			case '5': case '6': case '7': case '8': case '9':
+				break;
+			default:
+				token_init(&parser->token, parser,
+				    TOKEN_TYPE_NUMBER, token_pos, parser->pos -
+				    token_pos, token_line, token_col);
+				state = STATE_ACCEPT;
+				break;
+			}
+			break;
+		default:
+			not_reached();
+		}
+
+		if (state != STATE_ACCEPT) {
+			if (c == '\n') {
+				parser->line++;
+				parser->col = 0;
+			} else {
+				parser->col++;
+			}
+			parser->pos++;
+		}
+	}
+	return false;
+}
+
+static bool	parser_parse_array(parser_t *parser);
+static bool	parser_parse_object(parser_t *parser);
+
+static bool
+parser_parse_value(parser_t *parser)
+{
+	switch (parser->token.token_type) {
+	case TOKEN_TYPE_NULL:
+	case TOKEN_TYPE_FALSE:
+	case TOKEN_TYPE_TRUE:
+	case TOKEN_TYPE_STRING:
+	case TOKEN_TYPE_NUMBER:
+		return false;
+	case TOKEN_TYPE_LBRACE:
+		return parser_parse_object(parser);
+	case TOKEN_TYPE_LBRACKET:
+		return parser_parse_array(parser);
+	default:
+		return true;
+	}
+	not_reached();
+}
+
+static bool
+parser_parse_pair(parser_t *parser)
+{
+	assert_d_eq(parser->token.token_type, TOKEN_TYPE_STRING,
+	    "Pair should start with string");
+	if (parser_tokenize(parser)) {
+		return true;
+	}
+	switch (parser->token.token_type) {
+	case TOKEN_TYPE_COLON:
+		if (parser_tokenize(parser)) {
+			return true;
+		}
+		return parser_parse_value(parser);
+	default:
+		return true;
+	}
+}
+
+static bool
+parser_parse_values(parser_t *parser)
+{
+	if (parser_parse_value(parser)) {
+		return true;
+	}
+
+	while (true) {
+		if (parser_tokenize(parser)) {
+			return true;
+		}
+		switch (parser->token.token_type) {
+		case TOKEN_TYPE_COMMA:
+			if (parser_tokenize(parser)) {
+				return true;
+			}
+			if (parser_parse_value(parser)) {
+				return true;
+			}
+			break;
+		case TOKEN_TYPE_RBRACKET:
+			return false;
+		default:
+			return true;
+		}
+	}
+}
+
+static bool
+parser_parse_array(parser_t *parser)
+{
+	assert_d_eq(parser->token.token_type, TOKEN_TYPE_LBRACKET,
+	    "Array should start with [");
+	if (parser_tokenize(parser)) {
+		return true;
+	}
+	switch (parser->token.token_type) {
+	case TOKEN_TYPE_RBRACKET:
+		return false;
+	default:
+		return parser_parse_values(parser);
+	}
+	not_reached();
+}
+
+static bool
+parser_parse_pairs(parser_t *parser)
+{
+	assert_d_eq(parser->token.token_type, TOKEN_TYPE_STRING,
+	    "Object should start with string");
+	if (parser_parse_pair(parser)) {
+		return true;
+	}
+
+	while (true) {
+		if (parser_tokenize(parser)) {
+			return true;
+		}
+		switch (parser->token.token_type) {
+		case TOKEN_TYPE_COMMA:
+			if (parser_tokenize(parser)) {
+				return true;
+			}
+			switch (parser->token.token_type) {
+			case TOKEN_TYPE_STRING:
+				if (parser_parse_pair(parser)) {
+					return true;
+				}
+				break;
+			default:
+				return true;
+			}
+			break;
+		case TOKEN_TYPE_RBRACE:
+			return false;
+		default:
+			return true;
+		}
+	}
+}
+
+static bool
+parser_parse_object(parser_t *parser)
+{
+	assert_d_eq(parser->token.token_type, TOKEN_TYPE_LBRACE,
+	    "Object should start with {");
+	if (parser_tokenize(parser)) {
+		return true;
+	}
+	switch (parser->token.token_type) {
+	case TOKEN_TYPE_STRING:
+		return parser_parse_pairs(parser);
+	case TOKEN_TYPE_RBRACE:
+		return false;
+	default:
+		return true;
+	}
+	not_reached();
+}
+
+static bool
+parser_parse(parser_t *parser)
+{
+	if (parser_tokenize(parser)) {
+		goto label_error;
+	}
+	if (parser_parse_value(parser)) {
+		goto label_error;
+	}
+
+	if (parser_tokenize(parser)) {
+		goto label_error;
+	}
+	switch (parser->token.token_type) {
+	case TOKEN_TYPE_EOI:
+		return false;
+	default:
+		goto label_error;
+	}
+	not_reached();
+
+label_error:
+	token_error(&parser->token);
+	return true;
+}
+
+TEST_BEGIN(test_json_parser)
+{
+	size_t i;
+	const char *invalid_inputs[] = {
+		/* Tokenizer error case tests. */
+		"{ \"string\": X }",
+		"{ \"string\": nXll }",
+		"{ \"string\": nuXl }",
+		"{ \"string\": nulX }",
+		"{ \"string\": nullX }",
+		"{ \"string\": fXlse }",
+		"{ \"string\": faXse }",
+		"{ \"string\": falXe }",
+		"{ \"string\": falsX }",
+		"{ \"string\": falseX }",
+		"{ \"string\": tXue }",
+		"{ \"string\": trXe }",
+		"{ \"string\": truX }",
+		"{ \"string\": trueX }",
+		"{ \"string\": \"\n\" }",
+		"{ \"string\": \"\\z\" }",
+		"{ \"string\": \"\\uX000\" }",
+		"{ \"string\": \"\\u0X00\" }",
+		"{ \"string\": \"\\u00X0\" }",
+		"{ \"string\": \"\\u000X\" }",
+		"{ \"string\": -X }",
+		"{ \"string\": 0.X }",
+		"{ \"string\": 0.0eX }",
+		"{ \"string\": 0.0e+X }",
+
+		/* Parser error test cases. */
+		"{\"string\": }",
+		"{\"string\" }",
+		"{\"string\": [ 0 }",
+		"{\"string\": {\"a\":0, 1 } }",
+		"{\"string\": {\"a\":0: } }",
+		"{",
+		"{}{",
+	};
+	const char *valid_inputs[] = {
+		/* Token tests. */
+		"null",
+		"false",
+		"true",
+		"{}",
+		"{\"a\": 0}",
+		"[]",
+		"[0, 1]",
+		"0",
+		"1",
+		"10",
+		"-10",
+		"10.23",
+		"10.23e4",
+		"10.23e-4",
+		"10.23e+4",
+		"10.23E4",
+		"10.23E-4",
+		"10.23E+4",
+		"-10.23",
+		"-10.23e4",
+		"-10.23e-4",
+		"-10.23e+4",
+		"-10.23E4",
+		"-10.23E-4",
+		"-10.23E+4",
+		"\"value\"",
+		"\" \\\" \\/ \\b \\n \\r \\t \\u0abc \\u1DEF \"",
+
+		/* Parser test with various nesting. */
+		"{\"a\":null, \"b\":[1,[{\"c\":2},3]], \"d\":{\"e\":true}}",
+	};
+
+	for (i = 0; i < sizeof(invalid_inputs)/sizeof(const char *); i++) {
+		const char *input = invalid_inputs[i];
+		parser_t parser;
+		parser_init(&parser, false);
+		assert_false(parser_append(&parser, input),
+		    "Unexpected input appending failure");
+		assert_true(parser_parse(&parser),
+		    "Unexpected parse success for input: %s", input);
+		parser_fini(&parser);
+	}
+
+	for (i = 0; i < sizeof(valid_inputs)/sizeof(const char *); i++) {
+		const char *input = valid_inputs[i];
+		parser_t parser;
+		parser_init(&parser, true);
+		assert_false(parser_append(&parser, input),
+		    "Unexpected input appending failure");
+		assert_false(parser_parse(&parser),
+		    "Unexpected parse error for input: %s", input);
+		parser_fini(&parser);
+	}
+}
+TEST_END
+
+void
+write_cb(void *opaque, const char *str)
+{
+	parser_t *parser = (parser_t *)opaque;
+	if (parser_append(parser, str)) {
+		test_fail("Unexpected input appending failure");
+	}
+}
+
+TEST_BEGIN(test_stats_print_json)
+{
+	const char *opts[] = {
+		"J",
+		"Jg",
+		"Jm",
+		"Jgm",
+		"Ja",
+		"Jb",
+		"Jab",
+		"Jl",
+		"Jal",
+		"Jbl",
+		"Jabl",
+		"Jh",
+		"Jah",
+		"Jbh",
+		"Jabh",
+		"Jlh",
+		"Jalh",
+		"Jblh",
+		"Jablh",
+		"Jgmablh",
+	};
+	unsigned arena_ind, i;
+
+	for (i = 0; i < 2; i++) {
+		unsigned j;
+
+		switch (i) {
+		case 0:
+			break;
+		case 1: {
+			size_t sz = sizeof(arena_ind);
+			assert_d_eq(mallctl("arenas.extend", (void *)&arena_ind,
+			    &sz, NULL, 0), 0, "Unexpected mallctl failure");
+			break;
+		} default:
+			not_reached();
+		}
+
+		for (j = 0; j < sizeof(opts)/sizeof(const char *); j++) {
+			parser_t parser;
+
+			parser_init(&parser, true);
+			malloc_stats_print(write_cb, (void *)&parser, opts[j]);
+			assert_false(parser_parse(&parser),
+			    "Unexpected parse error, opts=\"%s\"", opts[j]);
+			parser_fini(&parser);
+		}
+	}
+}
+TEST_END
+
+int
+main(void)
+{
+	return (test(
+	    test_json_parser,
+	    test_stats_print_json));
+}
--- a/memory/jemalloc/src/test/unit/witness.c
+++ b/memory/jemalloc/src/test/unit/witness.c
@@ -1,19 +1,19 @@
 #include "test/jemalloc_test.h"
 
 static witness_lock_error_t *witness_lock_error_orig;
 static witness_owner_error_t *witness_owner_error_orig;
 static witness_not_owner_error_t *witness_not_owner_error_orig;
-static witness_lockless_error_t *witness_lockless_error_orig;
+static witness_depth_error_t *witness_depth_error_orig;
 
 static bool saw_lock_error;
 static bool saw_owner_error;
 static bool saw_not_owner_error;
-static bool saw_lockless_error;
+static bool saw_depth_error;
 
 static void
 witness_lock_error_intercept(const witness_list_t *witnesses,
     const witness_t *witness)
 {
 
 	saw_lock_error = true;
 }
@@ -28,20 +28,19 @@ witness_owner_error_intercept(const witn
 static void
 witness_not_owner_error_intercept(const witness_t *witness)
 {
 
 	saw_not_owner_error = true;
 }
 
 static void
-witness_lockless_error_intercept(const witness_list_t *witnesses)
-{
-
-	saw_lockless_error = true;
+witness_depth_error_intercept(const witness_list_t *witnesses,
+    witness_rank_t rank_inclusive, unsigned depth) {
+	saw_depth_error = true;
 }
 
 static int
 witness_comp(const witness_t *a, const witness_t *b)
 {
 
 	assert_u_eq(a->rank, b->rank, "Witnesses should have equal rank");
 
@@ -62,31 +61,46 @@ TEST_BEGIN(test_witness)
 	witness_t a, b;
 	tsdn_t *tsdn;
 
 	test_skip_if(!config_debug);
 
 	tsdn = tsdn_fetch();
 
 	witness_assert_lockless(tsdn);
+	witness_assert_depth(tsdn, 0);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)1U, 0);
 
 	witness_init(&a, "a", 1, NULL);
 	witness_assert_not_owner(tsdn, &a);
 	witness_lock(tsdn, &a);
 	witness_assert_owner(tsdn, &a);
+	witness_assert_depth(tsdn, 1);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)1U, 1);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)2U, 0);
 
 	witness_init(&b, "b", 2, NULL);
 	witness_assert_not_owner(tsdn, &b);
 	witness_lock(tsdn, &b);
 	witness_assert_owner(tsdn, &b);
+	witness_assert_depth(tsdn, 2);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)1U, 2);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)2U, 1);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)3U, 0);
 
 	witness_unlock(tsdn, &a);
+	witness_assert_depth(tsdn, 1);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)1U, 1);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)2U, 1);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)3U, 0);
 	witness_unlock(tsdn, &b);
 
 	witness_assert_lockless(tsdn);
+	witness_assert_depth(tsdn, 0);
+	witness_assert_depth_to_rank(tsdn, (witness_rank_t)1U, 0);
 }
 TEST_END
 
 TEST_BEGIN(test_witness_comp)
 {
 	witness_t a, b, c, d;
 	tsdn_t *tsdn;
 
@@ -95,42 +109,47 @@ TEST_BEGIN(test_witness_comp)
 	tsdn = tsdn_fetch();
 
 	witness_assert_lockless(tsdn);
 
 	witness_init(&a, "a", 1, witness_comp);
 	witness_assert_not_owner(tsdn, &a);
 	witness_lock(tsdn, &a);
 	witness_assert_owner(tsdn, &a);
+	witness_assert_depth(tsdn, 1);
 
 	witness_init(&b, "b", 1, witness_comp);
 	witness_assert_not_owner(tsdn, &b);
 	witness_lock(tsdn, &b);
 	witness_assert_owner(tsdn, &b);
+	witness_assert_depth(tsdn, 2);
 	witness_unlock(tsdn, &b);
+	witness_assert_depth(tsdn, 1);
 
 	witness_lock_error_orig = witness_lock_error;
 	witness_lock_error = witness_lock_error_intercept;
 	saw_lock_error = false;
 
 	witness_init(&c, "c", 1, witness_comp_reverse);
 	witness_assert_not_owner(tsdn, &c);
 	assert_false(saw_lock_error, "Unexpected witness lock error");
 	witness_lock(tsdn, &c);
 	assert_true(saw_lock_error, "Expected witness lock error");
 	witness_unlock(tsdn, &c);
+	witness_assert_depth(tsdn, 1);
 
 	saw_lock_error = false;
 
 	witness_init(&d, "d", 1, NULL);
 	witness_assert_not_owner(tsdn, &d);
 	assert_false(saw_lock_error, "Unexpected witness lock error");
 	witness_lock(tsdn, &d);
 	assert_true(saw_lock_error, "Expected witness lock error");
 	witness_unlock(tsdn, &d);
+	witness_assert_depth(tsdn, 1);
 
 	witness_unlock(tsdn, &a);
 
 	witness_assert_lockless(tsdn);
 
 	witness_lock_error = witness_lock_error_orig;
 }
 TEST_END
@@ -149,21 +168,23 @@ TEST_BEGIN(test_witness_reversal)
 	tsdn = tsdn_fetch();
 
 	witness_assert_lockless(tsdn);
 
 	witness_init(&a, "a", 1, NULL);
 	witness_init(&b, "b", 2, NULL);
 
 	witness_lock(tsdn, &b);
+	witness_assert_depth(tsdn, 1);
 	assert_false(saw_lock_error, "Unexpected witness lock error");
 	witness_lock(tsdn, &a);
 	assert_true(saw_lock_error, "Expected witness lock error");
 
 	witness_unlock(tsdn, &a);
+	witness_assert_depth(tsdn, 1);
 	witness_unlock(tsdn, &b);
 
 	witness_assert_lockless(tsdn);
 
 	witness_lock_error = witness_lock_error_orig;
 }
 TEST_END
 
@@ -227,52 +248,55 @@ TEST_BEGIN(test_witness_unlock_not_owned
 	assert_true(saw_owner_error, "Expected owner error");
 
 	witness_assert_lockless(tsdn);
 
 	witness_owner_error = witness_owner_error_orig;
 }
 TEST_END
 
-TEST_BEGIN(test_witness_lockful)
-{
+TEST_BEGIN(test_witness_depth) {
 	witness_t a;
 	tsdn_t *tsdn;
 
 	test_skip_if(!config_debug);
 
-	witness_lockless_error_orig = witness_lockless_error;
-	witness_lockless_error = witness_lockless_error_intercept;
-	saw_lockless_error = false;
+	witness_depth_error_orig = witness_depth_error;
+	witness_depth_error = witness_depth_error_intercept;
+	saw_depth_error = false;
 
 	tsdn = tsdn_fetch();
 
 	witness_assert_lockless(tsdn);
+	witness_assert_depth(tsdn, 0);
 
 	witness_init(&a, "a", 1, NULL);
 
-	assert_false(saw_lockless_error, "Unexpected lockless error");
+	assert_false(saw_depth_error, "Unexpected depth error");
 	witness_assert_lockless(tsdn);
+	witness_assert_depth(tsdn, 0);
 
 	witness_lock(tsdn, &a);
 	witness_assert_lockless(tsdn);
-	assert_true(saw_lockless_error, "Expected lockless error");
+	witness_assert_depth(tsdn, 0);
+	assert_true(saw_depth_error, "Expected depth error");
 
 	witness_unlock(tsdn, &a);
 
 	witness_assert_lockless(tsdn);
+	witness_assert_depth(tsdn, 0);
 
-	witness_lockless_error = witness_lockless_error_orig;
+	witness_depth_error = witness_depth_error_orig;
 }
 TEST_END
 
 int
 main(void)
 {
 
-	return (test(
+	return test(
 	    test_witness,
 	    test_witness_comp,
 	    test_witness_reversal,
 	    test_witness_recursive,
 	    test_witness_unlock_not_owned,
-	    test_witness_lockful));
+	    test_witness_depth);
 }
--- a/memory/jemalloc/src/test/unit/zero.c
+++ b/memory/jemalloc/src/test/unit/zero.c
@@ -1,15 +1,10 @@
 #include "test/jemalloc_test.h"
 
-#ifdef JEMALLOC_FILL
-const char *malloc_conf =
-    "abort:false,junk:false,zero:true,redzone:false,quarantine:0";
-#endif
-
 static void
 test_zero(size_t sz_min, size_t sz_max)
 {
 	uint8_t *s;
 	size_t sz_prev, sz, i;
 #define	MAGIC	((uint8_t)0x61)
 
 	sz_prev = 0;
new file mode 100644
--- /dev/null
+++ b/memory/jemalloc/src/test/unit/zero.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ "x${enable_fill}" = "x1" ] ; then
+  export MALLOC_CONF="abort:false,junk:false,zero:true,redzone:false,quarantine:0"
+fi
--- a/memory/jemalloc/upstream.info
+++ b/memory/jemalloc/upstream.info
@@ -1,2 +1,2 @@
 UPSTREAM_REPO=https://github.com/jemalloc/jemalloc
-UPSTREAM_COMMIT=c6943acb3c56d1b3d1e82dd43b3fcfeae7771990
+UPSTREAM_COMMIT=4.5.0