Fix extent_alloc_cache[_locked]() to support decommitted allocation.

Fix extent_alloc_cache[_locked]() to support decommitted allocation, and
use this ability in arena_stash_dirty(), so that decommitted extents are
not needlessly committed during purging.  In practice this does not
happen on any currently supported systems, because both extent merging
and decommit must be implemented; all supported systems implement one
xor the other.
diff --git a/include/jemalloc/internal/extent.h b/include/jemalloc/internal/extent.h
index 08d3036..673cac2 100644
--- a/include/jemalloc/internal/extent.h
+++ b/include/jemalloc/internal/extent.h
@@ -101,10 +101,10 @@
 
 extent_t	*extent_alloc_cache_locked(tsdn_t *tsdn, arena_t *arena,
     extent_hooks_t **r_extent_hooks, void *new_addr, size_t usize, size_t pad,
-    size_t alignment, bool *zero, bool slab);
+    size_t alignment, bool *zero, bool *commit, bool slab);
 extent_t	*extent_alloc_cache(tsdn_t *tsdn, arena_t *arena,
     extent_hooks_t **r_extent_hooks, void *new_addr, size_t usize, size_t pad,
-    size_t alignment, bool *zero, bool slab);
+    size_t alignment, bool *zero, bool *commit, bool slab);
 extent_t	*extent_alloc_wrapper(tsdn_t *tsdn, arena_t *arena,
     extent_hooks_t **r_extent_hooks, void *new_addr, size_t usize, size_t pad,
     size_t alignment, bool *zero, bool *commit, bool slab);
diff --git a/src/arena.c b/src/arena.c
index ce28959..fd3c553 100644
--- a/src/arena.c
+++ b/src/arena.c
@@ -49,11 +49,12 @@
     extent_hooks_t **r_extent_hooks, void *new_addr, size_t usize, size_t pad,
     size_t alignment, bool *zero, bool slab)
 {
+	bool commit = true;
 
 	malloc_mutex_assert_owner(tsdn, &arena->lock);
 
 	return (extent_alloc_cache(tsdn, arena, r_extent_hooks, new_addr, usize,
-	    pad, alignment, zero, slab));
+	    pad, alignment, zero, &commit, slab));
 }
 
 extent_t *
@@ -681,7 +682,7 @@
 	for (extent = qr_next(&arena->extents_dirty, qr_link); extent !=
 	    &arena->extents_dirty; extent = next) {
 		size_t npages;
-		bool zero;
+		bool zero, commit;
 		UNUSED extent_t *textent;
 
 		npages = extent_size_get(extent) >> LG_PAGE;
@@ -691,9 +692,10 @@
 		next = qr_next(extent, qr_link);
 		/* Allocate. */
 		zero = false;
+		commit = false;
 		textent = extent_alloc_cache_locked(tsdn, arena, r_extent_hooks,
 		    extent_base_get(extent), extent_size_get(extent), 0, PAGE,
-		    &zero, false);
+		    &zero, &commit, false);
 		assert(textent == extent);
 		assert(zero == extent_zeroed_get(extent));
 		extent_ring_remove(extent);
@@ -943,9 +945,8 @@
 	extent_t *slab;
 	arena_slab_data_t *slab_data;
 	extent_hooks_t *extent_hooks = EXTENT_HOOKS_INITIALIZER;
-	bool zero;
+	bool zero = false;
 
-	zero = false;
 	slab = arena_extent_cache_alloc_locked(tsdn, arena, &extent_hooks, NULL,
 	    bin_info->slab_size, 0, PAGE, &zero, true);
 	if (slab == NULL) {
diff --git a/src/extent.c b/src/extent.c
index 809777a..ad78c87 100644
--- a/src/extent.c
+++ b/src/extent.c
@@ -517,8 +517,9 @@
 		extent_usize_set(extent, usize);
 	}
 
-	if (!extent_committed_get(extent) && extent_commit_wrapper(tsdn, arena,
-	    r_extent_hooks, extent, 0, extent_size_get(extent))) {
+	if (commit && !extent_committed_get(extent) &&
+	    extent_commit_wrapper(tsdn, arena, r_extent_hooks, extent, 0,
+	    extent_size_get(extent))) {
 		if (!locked)
 			malloc_mutex_unlock(tsdn, &arena->extents_mtx);
 		extent_record(tsdn, arena, r_extent_hooks, extent_heaps, cache,
@@ -590,44 +591,41 @@
 static extent_t *
 extent_alloc_cache_impl(tsdn_t *tsdn, arena_t *arena,
     extent_hooks_t **r_extent_hooks, bool locked, void *new_addr, size_t usize,
-    size_t pad, size_t alignment, bool *zero, bool slab)
+    size_t pad, size_t alignment, bool *zero, bool *commit, bool slab)
 {
 	extent_t *extent;
-	bool commit;
 
 	assert(usize + pad != 0);
 	assert(alignment != 0);
 
-	commit = true;
 	extent = extent_recycle(tsdn, arena, r_extent_hooks,
 	    arena->extents_cached, locked, true, new_addr, usize, pad,
-	    alignment, zero, &commit, slab);
+	    alignment, zero, commit, slab);
 	if (extent == NULL)
 		return (NULL);
-	assert(commit);
 	return (extent);
 }
 
 extent_t *
 extent_alloc_cache_locked(tsdn_t *tsdn, arena_t *arena,
     extent_hooks_t **r_extent_hooks, void *new_addr, size_t usize, size_t pad,
-    size_t alignment, bool *zero, bool slab)
+    size_t alignment, bool *zero, bool *commit, bool slab)
 {
 
 	malloc_mutex_assert_owner(tsdn, &arena->extents_mtx);
 
 	return (extent_alloc_cache_impl(tsdn, arena, r_extent_hooks, true,
-	    new_addr, usize, pad, alignment, zero, slab));
+	    new_addr, usize, pad, alignment, zero, commit, slab));
 }
 
 extent_t *
 extent_alloc_cache(tsdn_t *tsdn, arena_t *arena,
     extent_hooks_t **r_extent_hooks, void *new_addr, size_t usize, size_t pad,
-    size_t alignment, bool *zero, bool slab)
+    size_t alignment, bool *zero, bool *commit, bool slab)
 {
 
 	return (extent_alloc_cache_impl(tsdn, arena, r_extent_hooks, false,
-	    new_addr, usize, pad, alignment, zero, slab));
+	    new_addr, usize, pad, alignment, zero, commit, slab));
 }
 
 static void *
diff --git a/src/large.c b/src/large.c
index 23af183..1bae939 100644
--- a/src/large.c
+++ b/src/large.c
@@ -143,8 +143,8 @@
 	extent_t *trail;
 
 	if ((trail = arena_extent_cache_alloc(tsdn, arena, &extent_hooks,
-	    extent_past_get(extent), trailsize, CACHELINE, &is_zeroed_trail))
-	    == NULL) {
+	    extent_past_get(extent), trailsize, CACHELINE, &is_zeroed_trail)) ==
+	    NULL) {
 		bool commit = true;
 		if ((trail = extent_alloc_wrapper(tsdn, arena, &extent_hooks,
 		    extent_past_get(extent), trailsize, 0, CACHELINE,