Home | History | Annotate | Download | only in vendor
      1 /* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
      2 /* vim:set softtabstop=8 shiftwidth=8: */
      3 /*-
      4  * Copyright (C) 2006-2008 Jason Evans <jasone (at) FreeBSD.org>.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice(s), this list of conditions and the following disclaimer as
     12  *    the first lines of this file unmodified other than the possible
     13  *    addition of one or more copyright notices.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice(s), this list of conditions and the following disclaimer in
     16  *    the documentation and/or other materials provided with the
     17  *    distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
     20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
     23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     26  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     28  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     29  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  *
     31  *******************************************************************************
     32  *
     33  * This allocator implementation is designed to provide scalable performance
     34  * for multi-threaded programs on multi-processor systems.  The following
     35  * features are included for this purpose:
     36  *
     37  *   + Multiple arenas are used if there are multiple CPUs, which reduces lock
     38  *     contention and cache sloshing.
     39  *
     40  *   + Cache line sharing between arenas is avoided for internal data
     41  *     structures.
     42  *
     43  *   + Memory is managed in chunks and runs (chunks can be split into runs),
     44  *     rather than as individual pages.  This provides a constant-time
     45  *     mechanism for associating allocations with particular arenas.
     46  *
     47  * Allocation requests are rounded up to the nearest size class, and no record
     48  * of the original request size is maintained.  Allocations are broken into
     49  * categories according to size class.  Assuming runtime defaults, 4 kB pages
     50  * and a 16 byte quantum on a 32-bit system, the size classes in each category
     51  * are as follows:
     52  *
     53  *   |=====================================|
     54  *   | Category | Subcategory    |    Size |
     55  *   |=====================================|
     56  *   | Small    | Tiny           |       2 |
     57  *   |          |                |       4 |
     58  *   |          |                |       8 |
     59  *   |          |----------------+---------|
     60  *   |          | Quantum-spaced |      16 |
     61  *   |          |                |      32 |
     62  *   |          |                |      48 |
     63  *   |          |                |     ... |
     64  *   |          |                |     480 |
     65  *   |          |                |     496 |
     66  *   |          |                |     512 |
     67  *   |          |----------------+---------|
     68  *   |          | Sub-page       |    1 kB |
     69  *   |          |                |    2 kB |
     70  *   |=====================================|
     71  *   | Large                     |    4 kB |
     72  *   |                           |    8 kB |
     73  *   |                           |   12 kB |
     74  *   |                           |     ... |
     75  *   |                           | 1012 kB |
     76  *   |                           | 1016 kB |
     77  *   |                           | 1020 kB |
     78  *   |=====================================|
     79  *   | Huge                      |    1 MB |
     80  *   |                           |    2 MB |
     81  *   |                           |    3 MB |
     82  *   |                           |     ... |
     83  *   |=====================================|
     84  *
     85  * A different mechanism is used for each category:
     86  *
     87  *   Small : Each size class is segregated into its own set of runs.  Each run
     88  *           maintains a bitmap of which regions are free/allocated.
     89  *
     90  *   Large : Each allocation is backed by a dedicated run.  Metadata are stored
     91  *           in the associated arena chunk header maps.
     92  *
     93  *   Huge : Each allocation is backed by a dedicated contiguous set of chunks.
     94  *          Metadata are stored in a separate red-black tree.
     95  *
     96  *******************************************************************************
     97  */
     98 
     99 /*
    100  * MALLOC_PRODUCTION disables assertions and statistics gathering.  It also
    101  * defaults the A and J runtime options to off.  These settings are appropriate
    102  * for production systems.
    103  */
    104 #ifndef MOZ_MEMORY_DEBUG
    105 #  define	MALLOC_PRODUCTION
    106 #endif
    107 
    108 /*
    109  * Use only one arena by default.  Mozilla does not currently make extensive
    110  * use of concurrent allocation, so the increased fragmentation associated with
    111  * multiple arenas is not warranted.
    112  */
    113 #define	MOZ_MEMORY_NARENAS_DEFAULT_ONE
    114 
    115 /*
    116  * MALLOC_STATS enables statistics calculation, and is required for
    117  * jemalloc_stats().
    118  */
    119 #define MALLOC_STATS
    120 
    121 #ifndef MALLOC_PRODUCTION
    122    /*
    123     * MALLOC_DEBUG enables assertions and other sanity checks, and disables
    124     * inline functions.
    125     */
    126 #  define MALLOC_DEBUG
    127 
    128    /* Memory filling (junk/zero). */
    129 #  define MALLOC_FILL
    130 
    131    /* Allocation tracing. */
    132 #  ifndef MOZ_MEMORY_WINDOWS
    133 #    define MALLOC_UTRACE
    134 #  endif
    135 
    136    /* Support optional abort() on OOM. */
    137 #  define MALLOC_XMALLOC
    138 
    139    /* Support SYSV semantics. */
    140 #  define MALLOC_SYSV
    141 #endif
    142 
    143 /*
    144  * MALLOC_VALIDATE causes malloc_usable_size() to perform some pointer
    145  * validation.  There are many possible errors that validation does not even
    146  * attempt to detect.
    147  */
    148 #define MALLOC_VALIDATE
    149 
    150 /* Embed no-op macros that support memory allocation tracking via valgrind. */
    151 #ifdef MOZ_VALGRIND
    152 #  define MALLOC_VALGRIND
    153 #endif
    154 #ifdef MALLOC_VALGRIND
    155 #  include <valgrind/valgrind.h>
    156 #else
    157 #  define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
    158 #  define VALGRIND_FREELIKE_BLOCK(addr, rzB)
    159 #endif
    160 
    161 /*
    162  * MALLOC_BALANCE enables monitoring of arena lock contention and dynamically
    163  * re-balances arena load if exponentially averaged contention exceeds a
    164  * certain threshold.
    165  */
    166 /* #define	MALLOC_BALANCE */
    167 
    168 #if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN))
    169    /*
    170     * MALLOC_PAGEFILE causes all mmap()ed memory to be backed by temporary
    171     * files, so that if a chunk is mapped, it is guaranteed to be swappable.
    172     * This avoids asynchronous OOM failures that are due to VM over-commit.
    173     *
    174     * XXX OS X over-commits, so we should probably use mmap() instead of
    175     * vm_allocate(), so that MALLOC_PAGEFILE works.
    176     */
    177 #define MALLOC_PAGEFILE
    178 #endif
    179 
    180 #ifdef MALLOC_PAGEFILE
    181 /* Write size when initializing a page file. */
    182 #  define MALLOC_PAGEFILE_WRITE_SIZE 512
    183 #endif
    184 
    185 #ifdef MOZ_MEMORY_LINUX
    186 #define	_GNU_SOURCE /* For mremap(2). */
    187 #define	issetugid() 0
    188 #if 0 /* Enable in order to test decommit code on Linux. */
    189 #  define MALLOC_DECOMMIT
    190 #endif
    191 #endif
    192 
    193 #ifndef MOZ_MEMORY_WINCE
    194 #include <sys/types.h>
    195 
    196 #include <errno.h>
    197 #include <stdlib.h>
    198 #endif
    199 #include <limits.h>
    200 #include <stdarg.h>
    201 #include <stdio.h>
    202 #include <string.h>
    203 
    204 #ifdef MOZ_MEMORY_WINDOWS
    205 #ifndef MOZ_MEMORY_WINCE
    206 #include <cruntime.h>
    207 #include <internal.h>
    208 #include <io.h>
    209 #else
    210 #include <cmnintrin.h>
    211 #include <crtdefs.h>
    212 #define SIZE_MAX UINT_MAX
    213 #endif
    214 #include <windows.h>
    215 
    216 #pragma warning( disable: 4267 4996 4146 )
    217 
    218 #define	false FALSE
    219 #define	true TRUE
    220 #define	inline __inline
    221 #define	SIZE_T_MAX SIZE_MAX
    222 #define	STDERR_FILENO 2
    223 #define	PATH_MAX MAX_PATH
    224 #define	vsnprintf _vsnprintf
    225 
    226 #ifndef NO_TLS
    227 static unsigned long tlsIndex = 0xffffffff;
    228 #endif
    229 
    230 #define	__thread
    231 #ifdef MOZ_MEMORY_WINCE
    232 #define	_pthread_self() GetCurrentThreadId()
    233 #else
    234 #define	_pthread_self() __threadid()
    235 #endif
    236 #define	issetugid() 0
    237 
    238 #ifndef MOZ_MEMORY_WINCE
    239 /* use MSVC intrinsics */
    240 #pragma intrinsic(_BitScanForward)
    241 static __forceinline int
    242 ffs(int x)
    243 {
    244 	unsigned long i;
    245 
    246 	if (_BitScanForward(&i, x) != 0)
    247 		return (i + 1);
    248 
    249 	return (0);
    250 }
    251 
    252 /* Implement getenv without using malloc */
    253 static char mozillaMallocOptionsBuf[64];
    254 
    255 #define	getenv xgetenv
    256 static char *
    257 getenv(const char *name)
    258 {
    259 
    260 	if (GetEnvironmentVariableA(name, (LPSTR)&mozillaMallocOptionsBuf,
    261 		    sizeof(mozillaMallocOptionsBuf)) > 0)
    262 		return (mozillaMallocOptionsBuf);
    263 
    264 	return (NULL);
    265 }
    266 
    267 #else /* WIN CE */
    268 
    269 #define ENOMEM          12
    270 #define EINVAL          22
    271 
    272 static __forceinline int
    273 ffs(int x)
    274 {
    275 
    276 	return 32 - _CountLeadingZeros((-x) & x);
    277 }
    278 #endif
    279 
    280 typedef unsigned char uint8_t;
    281 typedef unsigned uint32_t;
    282 typedef unsigned long long uint64_t;
    283 typedef unsigned long long uintmax_t;
    284 typedef long ssize_t;
    285 
    286 #define	MALLOC_DECOMMIT
    287 #endif
    288 
    289 #ifndef MOZ_MEMORY_WINDOWS
    290 #ifndef MOZ_MEMORY_SOLARIS
    291 #include <sys/cdefs.h>
    292 #endif
    293 #ifndef __DECONST
    294 #  define __DECONST(type, var)	((type)(uintptr_t)(const void *)(var))
    295 #endif
    296 #ifndef MOZ_MEMORY
    297 __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 180599 2008-07-18 19:35:44Z jasone $");
    298 #include "libc_private.h"
    299 #ifdef MALLOC_DEBUG
    300 #  define _LOCK_DEBUG
    301 #endif
    302 #include "spinlock.h"
    303 #include "namespace.h"
    304 #endif
    305 #include <sys/mman.h>
    306 #ifndef MADV_FREE
    307 #  define MADV_FREE	MADV_DONTNEED
    308 #endif
    309 #ifndef MAP_NOSYNC
    310 #  define MAP_NOSYNC	0
    311 #endif
    312 #include <sys/param.h>
    313 #ifndef MOZ_MEMORY
    314 #include <sys/stddef.h>
    315 #endif
    316 #include <sys/time.h>
    317 #include <sys/types.h>
    318 #ifndef MOZ_MEMORY_SOLARIS
    319 #include <sys/sysctl.h>
    320 #endif
    321 #include <sys/uio.h>
    322 #ifndef MOZ_MEMORY
    323 #include <sys/ktrace.h> /* Must come after several other sys/ includes. */
    324 
    325 #include <machine/atomic.h>
    326 #include <machine/cpufunc.h>
    327 #include <machine/vmparam.h>
    328 #endif
    329 
    330 #include <errno.h>
    331 #include <limits.h>
    332 #ifndef SIZE_T_MAX
    333 #  define SIZE_T_MAX	SIZE_MAX
    334 #endif
    335 #include <pthread.h>
    336 #ifdef MOZ_MEMORY_DARWIN
    337 #define _pthread_self pthread_self
    338 #define _pthread_mutex_init pthread_mutex_init
    339 #define _pthread_mutex_trylock pthread_mutex_trylock
    340 #define _pthread_mutex_lock pthread_mutex_lock
    341 #define _pthread_mutex_unlock pthread_mutex_unlock
    342 #endif
    343 #include <sched.h>
    344 #include <stdarg.h>
    345 #include <stdbool.h>
    346 #include <stdio.h>
    347 #include <stdint.h>
    348 #include <stdlib.h>
    349 #include <string.h>
    350 #ifndef MOZ_MEMORY_DARWIN
    351 #include <strings.h>
    352 #endif
    353 #include <unistd.h>
    354 
    355 #ifdef MOZ_MEMORY_DARWIN
    356 #include <libkern/OSAtomic.h>
    357 #include <mach/mach_error.h>
    358 #include <mach/mach_init.h>
    359 #include <mach/vm_map.h>
    360 #include <malloc/malloc.h>
    361 #endif
    362 
    363 #ifndef MOZ_MEMORY
    364 #include "un-namespace.h"
    365 #endif
    366 
    367 #endif
    368 
    369 #include "jemalloc.h"
    370 
    371 #undef bool
    372 #define bool jemalloc_bool
    373 
    374 #ifdef MOZ_MEMORY_DARWIN
    375 static const bool __isthreaded = true;
    376 #endif
    377 
    378 #if defined(MOZ_MEMORY_SOLARIS) && defined(MAP_ALIGN) && !defined(JEMALLOC_NEVER_USES_MAP_ALIGN)
    379 #define JEMALLOC_USES_MAP_ALIGN	 /* Required on Solaris 10. Might improve performance elsewhere. */
    380 #endif
    381 
    382 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
    383 #define JEMALLOC_USES_MAP_ALIGN	 /* Required for Windows CE < 6 */
    384 #endif
    385 
    386 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
    387 
    388 #include "qr.h"
    389 #include "ql.h"
    390 #ifdef MOZ_MEMORY_WINDOWS
    391    /* MSVC++ does not support C99 variable-length arrays. */
    392 #  define RB_NO_C99_VARARRAYS
    393 #endif
    394 #include "rb.h"
    395 
    396 #ifdef MALLOC_DEBUG
    397    /* Disable inlining to make debugging easier. */
    398 #ifdef inline
    399 #undef inline
    400 #endif
    401 
    402 #  define inline
    403 #endif
    404 
    405 /* Size of stack-allocated buffer passed to strerror_r(). */
    406 #define	STRERROR_BUF		64
    407 
    408 /* Minimum alignment of allocations is 2^QUANTUM_2POW_MIN bytes. */
    409 #  define QUANTUM_2POW_MIN      4
    410 #ifdef MOZ_MEMORY_SIZEOF_PTR_2POW
    411 #  define SIZEOF_PTR_2POW		MOZ_MEMORY_SIZEOF_PTR_2POW
    412 #else
    413 #  define SIZEOF_PTR_2POW       2
    414 #endif
    415 #define PIC
    416 #ifndef MOZ_MEMORY_DARWIN
    417 static const bool __isthreaded = true;
    418 #else
    419 #  define NO_TLS
    420 #endif
    421 #if 0
    422 #ifdef __i386__
    423 #  define QUANTUM_2POW_MIN	4
    424 #  define SIZEOF_PTR_2POW	2
    425 #  define CPU_SPINWAIT		__asm__ volatile("pause")
    426 #endif
    427 #ifdef __ia64__
    428 #  define QUANTUM_2POW_MIN	4
    429 #  define SIZEOF_PTR_2POW	3
    430 #endif
    431 #ifdef __alpha__
    432 #  define QUANTUM_2POW_MIN	4
    433 #  define SIZEOF_PTR_2POW	3
    434 #  define NO_TLS
    435 #endif
    436 #ifdef __sparc64__
    437 #  define QUANTUM_2POW_MIN	4
    438 #  define SIZEOF_PTR_2POW	3
    439 #  define NO_TLS
    440 #endif
    441 #ifdef __amd64__
    442 #  define QUANTUM_2POW_MIN	4
    443 #  define SIZEOF_PTR_2POW	3
    444 #  define CPU_SPINWAIT		__asm__ volatile("pause")
    445 #endif
    446 #ifdef __arm__
    447 #  define QUANTUM_2POW_MIN	3
    448 #  define SIZEOF_PTR_2POW	2
    449 #  define NO_TLS
    450 #endif
    451 #ifdef __mips__
    452 #  define QUANTUM_2POW_MIN	3
    453 #  define SIZEOF_PTR_2POW	2
    454 #  define NO_TLS
    455 #endif
    456 #ifdef __powerpc__
    457 #  define QUANTUM_2POW_MIN	4
    458 #  define SIZEOF_PTR_2POW	2
    459 #endif
    460 #endif
    461 
    462 #define	SIZEOF_PTR		(1U << SIZEOF_PTR_2POW)
    463 
    464 /* sizeof(int) == (1U << SIZEOF_INT_2POW). */
    465 #ifndef SIZEOF_INT_2POW
    466 #  define SIZEOF_INT_2POW	2
    467 #endif
    468 
    469 /* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */
    470 #if (!defined(PIC) && !defined(NO_TLS))
    471 #  define NO_TLS
    472 #endif
    473 
    474 #ifdef NO_TLS
    475    /* MALLOC_BALANCE requires TLS. */
    476 #  ifdef MALLOC_BALANCE
    477 #    undef MALLOC_BALANCE
    478 #  endif
    479 #endif
    480 
    481 /*
    482  * Size and alignment of memory chunks that are allocated by the OS's virtual
    483  * memory system.
    484  */
    485 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
    486 #define	CHUNK_2POW_DEFAULT	21
    487 #else
    488 #define	CHUNK_2POW_DEFAULT	20
    489 #endif
    490 /* Maximum number of dirty pages per arena. */
    491 #define	DIRTY_MAX_DEFAULT	(1U << 10)
    492 
    493 /* Default reserve chunks. */
    494 #define	RESERVE_MIN_2POW_DEFAULT	1
    495 /*
    496  * Default range (in chunks) between reserve_min and reserve_max, in addition
    497  * to the mandatory one chunk per arena.
    498  */
    499 #ifdef MALLOC_PAGEFILE
    500 #  define RESERVE_RANGE_2POW_DEFAULT	5
    501 #else
    502 #  define RESERVE_RANGE_2POW_DEFAULT	0
    503 #endif
    504 
    505 /*
    506  * Maximum size of L1 cache line.  This is used to avoid cache line aliasing,
    507  * so over-estimates are okay (up to a point), but under-estimates will
    508  * negatively affect performance.
    509  */
    510 #define	CACHELINE_2POW		6
    511 #define	CACHELINE		((size_t)(1U << CACHELINE_2POW))
    512 
    513 /* Smallest size class to support. */
    514 #define	TINY_MIN_2POW		1
    515 
    516 /*
    517  * Maximum size class that is a multiple of the quantum, but not (necessarily)
    518  * a power of 2.  Above this size, allocations are rounded up to the nearest
    519  * power of 2.
    520  */
    521 #define	SMALL_MAX_2POW_DEFAULT	9
    522 #define	SMALL_MAX_DEFAULT	(1U << SMALL_MAX_2POW_DEFAULT)
    523 
    524 /*
    525  * RUN_MAX_OVRHD indicates maximum desired run header overhead.  Runs are sized
    526  * as small as possible such that this setting is still honored, without
    527  * violating other constraints.  The goal is to make runs as small as possible
    528  * without exceeding a per run external fragmentation threshold.
    529  *
    530  * We use binary fixed point math for overhead computations, where the binary
    531  * point is implicitly RUN_BFP bits to the left.
    532  *
    533  * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
    534  * honored for some/all object sizes, since there is one bit of header overhead
    535  * per object (plus a constant).  This constraint is relaxed (ignored) for runs
    536  * that are so small that the per-region overhead is greater than:
    537  *
    538  *   (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
    539  */
    540 #define	RUN_BFP			12
    541 /*                                    \/   Implicit binary fixed point. */
    542 #define	RUN_MAX_OVRHD		0x0000003dU
    543 #define	RUN_MAX_OVRHD_RELAX	0x00001800U
    544 
    545 /* Put a cap on small object run size.  This overrides RUN_MAX_OVRHD. */
    546 #define	RUN_MAX_SMALL_2POW	15
    547 #define	RUN_MAX_SMALL		(1U << RUN_MAX_SMALL_2POW)
    548 
    549 /*
    550  * Hyper-threaded CPUs may need a special instruction inside spin loops in
    551  * order to yield to another virtual CPU.  If no such instruction is defined
    552  * above, make CPU_SPINWAIT a no-op.
    553  */
    554 #ifndef CPU_SPINWAIT
    555 #  define CPU_SPINWAIT
    556 #endif
    557 
    558 /*
    559  * Adaptive spinning must eventually switch to blocking, in order to avoid the
    560  * potential for priority inversion deadlock.  Backing off past a certain point
    561  * can actually waste time.
    562  */
    563 #define	SPIN_LIMIT_2POW		11
    564 
    565 /*
    566  * Conversion from spinning to blocking is expensive; we use (1U <<
    567  * BLOCK_COST_2POW) to estimate how many more times costly blocking is than
    568  * worst-case spinning.
    569  */
    570 #define	BLOCK_COST_2POW		4
    571 
    572 #ifdef MALLOC_BALANCE
    573    /*
    574     * We use an exponential moving average to track recent lock contention,
    575     * where the size of the history window is N, and alpha=2/(N+1).
    576     *
    577     * Due to integer math rounding, very small values here can cause
    578     * substantial degradation in accuracy, thus making the moving average decay
    579     * faster than it would with precise calculation.
    580     */
    581 #  define BALANCE_ALPHA_INV_2POW	9
    582 
    583    /*
    584     * Threshold value for the exponential moving contention average at which to
    585     * re-assign a thread.
    586     */
    587 #  define BALANCE_THRESHOLD_DEFAULT	(1U << (SPIN_LIMIT_2POW-4))
    588 #endif
    589 
    590 /******************************************************************************/
    591 
    592 /*
    593  * Mutexes based on spinlocks.  We can't use normal pthread spinlocks in all
    594  * places, because they require malloc()ed memory, which causes bootstrapping
    595  * issues in some cases.
    596  */
    597 #if defined(MOZ_MEMORY_WINDOWS)
    598 #define malloc_mutex_t CRITICAL_SECTION
    599 #define malloc_spinlock_t CRITICAL_SECTION
    600 #elif defined(MOZ_MEMORY_DARWIN)
    601 typedef struct {
    602 	OSSpinLock	lock;
    603 } malloc_mutex_t;
    604 typedef struct {
    605 	OSSpinLock	lock;
    606 } malloc_spinlock_t;
    607 #elif defined(MOZ_MEMORY)
    608 typedef pthread_mutex_t malloc_mutex_t;
    609 typedef pthread_mutex_t malloc_spinlock_t;
    610 #else
    611 /* XXX these should #ifdef these for freebsd (and linux?) only */
    612 typedef struct {
    613 	spinlock_t	lock;
    614 } malloc_mutex_t;
    615 typedef malloc_spinlock_t malloc_mutex_t;
    616 #endif
    617 
    618 /* Set to true once the allocator has been initialized. */
    619 static bool malloc_initialized = false;
    620 
    621 #if defined(MOZ_MEMORY_WINDOWS)
    622 /* No init lock for Windows. */
    623 #elif defined(MOZ_MEMORY_DARWIN)
    624 static malloc_mutex_t init_lock = {OS_SPINLOCK_INIT};
    625 #elif defined(MOZ_MEMORY_LINUX)
    626 static malloc_mutex_t init_lock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
    627 #elif defined(MOZ_MEMORY)
    628 static malloc_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
    629 #else
    630 static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER};
    631 #endif
    632 
    633 /******************************************************************************/
    634 /*
    635  * Statistics data structures.
    636  */
    637 
    638 #ifdef MALLOC_STATS
    639 
    640 typedef struct malloc_bin_stats_s malloc_bin_stats_t;
    641 struct malloc_bin_stats_s {
    642 	/*
    643 	 * Number of allocation requests that corresponded to the size of this
    644 	 * bin.
    645 	 */
    646 	uint64_t	nrequests;
    647 
    648 	/* Total number of runs created for this bin's size class. */
    649 	uint64_t	nruns;
    650 
    651 	/*
    652 	 * Total number of runs reused by extracting them from the runs tree for
    653 	 * this bin's size class.
    654 	 */
    655 	uint64_t	reruns;
    656 
    657 	/* High-water mark for this bin. */
    658 	unsigned long	highruns;
    659 
    660 	/* Current number of runs in this bin. */
    661 	unsigned long	curruns;
    662 };
    663 
    664 typedef struct arena_stats_s arena_stats_t;
    665 struct arena_stats_s {
    666 	/* Number of bytes currently mapped. */
    667 	size_t		mapped;
    668 
    669 	/*
    670 	 * Total number of purge sweeps, total number of madvise calls made,
    671 	 * and total pages purged in order to keep dirty unused memory under
    672 	 * control.
    673 	 */
    674 	uint64_t	npurge;
    675 	uint64_t	nmadvise;
    676 	uint64_t	purged;
    677 #ifdef MALLOC_DECOMMIT
    678 	/*
    679 	 * Total number of decommit/commit operations, and total number of
    680 	 * pages decommitted.
    681 	 */
    682 	uint64_t	ndecommit;
    683 	uint64_t	ncommit;
    684 	uint64_t	decommitted;
    685 #endif
    686 
    687 	/* Per-size-category statistics. */
    688 	size_t		allocated_small;
    689 	uint64_t	nmalloc_small;
    690 	uint64_t	ndalloc_small;
    691 
    692 	size_t		allocated_large;
    693 	uint64_t	nmalloc_large;
    694 	uint64_t	ndalloc_large;
    695 
    696 #ifdef MALLOC_BALANCE
    697 	/* Number of times this arena reassigned a thread due to contention. */
    698 	uint64_t	nbalance;
    699 #endif
    700 };
    701 
    702 typedef struct chunk_stats_s chunk_stats_t;
    703 struct chunk_stats_s {
    704 	/* Number of chunks that were allocated. */
    705 	uint64_t	nchunks;
    706 
    707 	/* High-water mark for number of chunks allocated. */
    708 	unsigned long	highchunks;
    709 
    710 	/*
    711 	 * Current number of chunks allocated.  This value isn't maintained for
    712 	 * any other purpose, so keep track of it in order to be able to set
    713 	 * highchunks.
    714 	 */
    715 	unsigned long	curchunks;
    716 };
    717 
    718 #endif /* #ifdef MALLOC_STATS */
    719 
    720 /******************************************************************************/
    721 /*
    722  * Extent data structures.
    723  */
    724 
    725 /* Tree of extents. */
    726 typedef struct extent_node_s extent_node_t;
    727 struct extent_node_s {
    728 	/* Linkage for the size/address-ordered tree. */
    729 	rb_node(extent_node_t) link_szad;
    730 
    731 	/* Linkage for the address-ordered tree. */
    732 	rb_node(extent_node_t) link_ad;
    733 
    734 	/* Pointer to the extent that this tree node is responsible for. */
    735 	void	*addr;
    736 
    737 	/* Total region size. */
    738 	size_t	size;
    739 };
    740 typedef rb_tree(extent_node_t) extent_tree_t;
    741 
    742 /******************************************************************************/
    743 /*
    744  * Radix tree data structures.
    745  */
    746 
    747 #ifdef MALLOC_VALIDATE
    748    /*
    749     * Size of each radix tree node (must be a power of 2).  This impacts tree
    750     * depth.
    751     */
    752 #  if (SIZEOF_PTR == 4)
    753 #    define MALLOC_RTREE_NODESIZE (1U << 14)
    754 #  else
    755 #    define MALLOC_RTREE_NODESIZE CACHELINE
    756 #  endif
    757 
    758 typedef struct malloc_rtree_s malloc_rtree_t;
    759 struct malloc_rtree_s {
    760 	malloc_spinlock_t	lock;
    761 	void			**root;
    762 	unsigned		height;
    763 	unsigned		level2bits[1]; /* Dynamically sized. */
    764 };
    765 #endif
    766 
    767 /******************************************************************************/
    768 /*
    769  * Reserve data structures.
    770  */
    771 
    772 /* Callback registration. */
    773 typedef struct reserve_reg_s reserve_reg_t;
    774 struct reserve_reg_s {
    775 	/* Linkage for list of all registered callbacks. */
    776 	ql_elm(reserve_reg_t)	link;
    777 
    778 	/* Callback function pointer. */
    779 	reserve_cb_t		*cb;
    780 
    781 	/* Opaque application data pointer. */
    782 	void			*ctx;
    783 
    784 	/*
    785 	 * Sequence number of condition notification most recently sent to this
    786 	 * callback.
    787 	 */
    788 	uint64_t		seq;
    789 };
    790 
    791 /******************************************************************************/
    792 /*
    793  * Arena data structures.
    794  */
    795 
    796 typedef struct arena_s arena_t;
    797 typedef struct arena_bin_s arena_bin_t;
    798 
    799 /* Each element of the chunk map corresponds to one page within the chunk. */
    800 typedef struct arena_chunk_map_s arena_chunk_map_t;
    801 struct arena_chunk_map_s {
    802 	/*
    803 	 * Linkage for run trees.  There are two disjoint uses:
    804 	 *
    805 	 * 1) arena_t's runs_avail tree.
    806 	 * 2) arena_run_t conceptually uses this linkage for in-use non-full
    807 	 *    runs, rather than directly embedding linkage.
    808 	 */
    809 	rb_node(arena_chunk_map_t)	link;
    810 
    811 	/*
    812 	 * Run address (or size) and various flags are stored together.  The bit
    813 	 * layout looks like (assuming 32-bit system):
    814 	 *
    815 	 *   ???????? ???????? ????---- --ckdzla
    816 	 *
    817 	 * ? : Unallocated: Run address for first/last pages, unset for internal
    818 	 *                  pages.
    819 	 *     Small: Run address.
    820 	 *     Large: Run size for first page, unset for trailing pages.
    821 	 * - : Unused.
    822 	 * c : decommitted?
    823 	 * k : key?
    824 	 * d : dirty?
    825 	 * z : zeroed?
    826 	 * l : large?
    827 	 * a : allocated?
    828 	 *
    829 	 * Following are example bit patterns for the three types of runs.
    830 	 *
    831 	 * r : run address
    832 	 * s : run size
    833 	 * x : don't care
    834 	 * - : 0
    835 	 * [cdzla] : bit set
    836 	 *
    837 	 *   Unallocated:
    838 	 *     ssssssss ssssssss ssss---- --c-----
    839 	 *     xxxxxxxx xxxxxxxx xxxx---- ----d---
    840 	 *     ssssssss ssssssss ssss---- -----z--
    841 	 *
    842 	 *   Small:
    843 	 *     rrrrrrrr rrrrrrrr rrrr---- -------a
    844 	 *     rrrrrrrr rrrrrrrr rrrr---- -------a
    845 	 *     rrrrrrrr rrrrrrrr rrrr---- -------a
    846 	 *
    847 	 *   Large:
    848 	 *     ssssssss ssssssss ssss---- ------la
    849 	 *     -------- -------- -------- ------la
    850 	 *     -------- -------- -------- ------la
    851 	 */
    852 	size_t				bits;
    853 #ifdef MALLOC_DECOMMIT
    854 #define	CHUNK_MAP_DECOMMITTED	((size_t)0x20U)
    855 #endif
    856 #define	CHUNK_MAP_KEY		((size_t)0x10U)
    857 #define	CHUNK_MAP_DIRTY		((size_t)0x08U)
    858 #define	CHUNK_MAP_ZEROED	((size_t)0x04U)
    859 #define	CHUNK_MAP_LARGE		((size_t)0x02U)
    860 #define	CHUNK_MAP_ALLOCATED	((size_t)0x01U)
    861 };
    862 typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;
    863 typedef rb_tree(arena_chunk_map_t) arena_run_tree_t;
    864 
    865 /* Arena chunk header. */
    866 typedef struct arena_chunk_s arena_chunk_t;
    867 struct arena_chunk_s {
    868 	/* Arena that owns the chunk. */
    869 	arena_t		*arena;
    870 
    871 	/* Linkage for the arena's chunks_dirty tree. */
    872 	rb_node(arena_chunk_t) link_dirty;
    873 
    874 	/* Number of dirty pages. */
    875 	size_t		ndirty;
    876 
    877 	/* Map of pages within chunk that keeps track of free/large/small. */
    878 	arena_chunk_map_t map[1]; /* Dynamically sized. */
    879 };
    880 typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
    881 
    882 typedef struct arena_run_s arena_run_t;
    883 struct arena_run_s {
    884 #ifdef MALLOC_DEBUG
    885 	uint32_t	magic;
    886 #  define ARENA_RUN_MAGIC 0x384adf93
    887 #endif
    888 
    889 	/* Bin this run is associated with. */
    890 	arena_bin_t	*bin;
    891 
    892 	/* Index of first element that might have a free region. */
    893 	unsigned	regs_minelm;
    894 
    895 	/* Number of free regions in run. */
    896 	unsigned	nfree;
    897 
    898 	/* Bitmask of in-use regions (0: in use, 1: free). */
    899 	unsigned	regs_mask[1]; /* Dynamically sized. */
    900 };
    901 
    902 struct arena_bin_s {
    903 	/*
    904 	 * Current run being used to service allocations of this bin's size
    905 	 * class.
    906 	 */
    907 	arena_run_t	*runcur;
    908 
    909 	/*
    910 	 * Tree of non-full runs.  This tree is used when looking for an
    911 	 * existing run when runcur is no longer usable.  We choose the
    912 	 * non-full run that is lowest in memory; this policy tends to keep
    913 	 * objects packed well, and it can also help reduce the number of
    914 	 * almost-empty chunks.
    915 	 */
    916 	arena_run_tree_t runs;
    917 
    918 	/* Size of regions in a run for this bin's size class. */
    919 	size_t		reg_size;
    920 
    921 	/* Total size of a run for this bin's size class. */
    922 	size_t		run_size;
    923 
    924 	/* Total number of regions in a run for this bin's size class. */
    925 	uint32_t	nregs;
    926 
    927 	/* Number of elements in a run's regs_mask for this bin's size class. */
    928 	uint32_t	regs_mask_nelms;
    929 
    930 	/* Offset of first region in a run for this bin's size class. */
    931 	uint32_t	reg0_offset;
    932 
    933 #ifdef MALLOC_STATS
    934 	/* Bin statistics. */
    935 	malloc_bin_stats_t stats;
    936 #endif
    937 };
    938 
    939 struct arena_s {
    940 #ifdef MALLOC_DEBUG
    941 	uint32_t		magic;
    942 #  define ARENA_MAGIC 0x947d3d24
    943 #endif
    944 
    945 	/* All operations on this arena require that lock be locked. */
    946 #ifdef MOZ_MEMORY
    947 	malloc_spinlock_t	lock;
    948 #else
    949 	pthread_mutex_t		lock;
    950 #endif
    951 
    952 #ifdef MALLOC_STATS
    953 	arena_stats_t		stats;
    954 #endif
    955 
    956 	/*
    957 	 * Chunk allocation sequence number, used to detect races with other
    958 	 * threads during chunk allocation, and then discard unnecessary chunks.
    959 	 */
    960 	uint64_t		chunk_seq;
    961 
    962 	/* Tree of dirty-page-containing chunks this arena manages. */
    963 	arena_chunk_tree_t	chunks_dirty;
    964 
    965 	/*
    966 	 * In order to avoid rapid chunk allocation/deallocation when an arena
    967 	 * oscillates right on the cusp of needing a new chunk, cache the most
    968 	 * recently freed chunk.  The spare is left in the arena's chunk trees
    969 	 * until it is deleted.
    970 	 *
    971 	 * There is one spare chunk per arena, rather than one spare total, in
    972 	 * order to avoid interactions between multiple threads that could make
    973 	 * a single spare inadequate.
    974 	 */
    975 	arena_chunk_t		*spare;
    976 
    977 	/*
    978 	 * Current count of pages within unused runs that are potentially
    979 	 * dirty, and for which madvise(... MADV_FREE) has not been called.  By
    980 	 * tracking this, we can institute a limit on how much dirty unused
    981 	 * memory is mapped for each arena.
    982 	 */
    983 	size_t			ndirty;
    984 
    985 	/*
    986 	 * Size/address-ordered tree of this arena's available runs.  This tree
    987 	 * is used for first-best-fit run allocation.
    988 	 */
    989 	arena_avail_tree_t	runs_avail;
    990 
    991 #ifdef MALLOC_BALANCE
    992 	/*
    993 	 * The arena load balancing machinery needs to keep track of how much
    994 	 * lock contention there is.  This value is exponentially averaged.
    995 	 */
    996 	uint32_t		contention;
    997 #endif
    998 
    999 	/*
   1000 	 * bins is used to store rings of free regions of the following sizes,
   1001 	 * assuming a 16-byte quantum, 4kB pagesize, and default MALLOC_OPTIONS.
   1002 	 *
   1003 	 *   bins[i] | size |
   1004 	 *   --------+------+
   1005 	 *        0  |    2 |
   1006 	 *        1  |    4 |
   1007 	 *        2  |    8 |
   1008 	 *   --------+------+
   1009 	 *        3  |   16 |
   1010 	 *        4  |   32 |
   1011 	 *        5  |   48 |
   1012 	 *        6  |   64 |
   1013 	 *           :      :
   1014 	 *           :      :
   1015 	 *       33  |  496 |
   1016 	 *       34  |  512 |
   1017 	 *   --------+------+
   1018 	 *       35  | 1024 |
   1019 	 *       36  | 2048 |
   1020 	 *   --------+------+
   1021 	 */
   1022 	arena_bin_t		bins[1]; /* Dynamically sized. */
   1023 };
   1024 
   1025 /******************************************************************************/
   1026 /*
   1027  * Data.
   1028  */
   1029 
   1030 /* Number of CPUs. */
   1031 static unsigned		ncpus;
   1032 
   1033 /* VM page size. */
   1034 static size_t		pagesize;
   1035 static size_t		pagesize_mask;
   1036 static size_t		pagesize_2pow;
   1037 
   1038 /* Various bin-related settings. */
   1039 static size_t		bin_maxclass; /* Max size class for bins. */
   1040 static unsigned		ntbins; /* Number of (2^n)-spaced tiny bins. */
   1041 static unsigned		nqbins; /* Number of quantum-spaced bins. */
   1042 static unsigned		nsbins; /* Number of (2^n)-spaced sub-page bins. */
   1043 static size_t		small_min;
   1044 static size_t		small_max;
   1045 
   1046 /* Various quantum-related settings. */
   1047 static size_t		quantum;
   1048 static size_t		quantum_mask; /* (quantum - 1). */
   1049 
   1050 /* Various chunk-related settings. */
   1051 static size_t		chunksize;
   1052 static size_t		chunksize_mask; /* (chunksize - 1). */
   1053 static size_t		chunk_npages;
   1054 static size_t		arena_chunk_header_npages;
   1055 static size_t		arena_maxclass; /* Max size class for arenas. */
   1056 
   1057 /********/
   1058 /*
   1059  * Chunks.
   1060  */
   1061 
   1062 #ifdef MALLOC_VALIDATE
   1063 static malloc_rtree_t *chunk_rtree;
   1064 #endif
   1065 
   1066 /* Protects chunk-related data structures. */
   1067 static malloc_mutex_t	huge_mtx;
   1068 
   1069 /* Tree of chunks that are stand-alone huge allocations. */
   1070 static extent_tree_t	huge;
   1071 
   1072 #ifdef MALLOC_STATS
   1073 /* Huge allocation statistics. */
   1074 static uint64_t		huge_nmalloc;
   1075 static uint64_t		huge_ndalloc;
   1076 static size_t		huge_allocated;
   1077 #endif
   1078 
   1079 /****************/
   1080 /*
   1081  * Memory reserve.
   1082  */
   1083 
   1084 #ifdef MALLOC_PAGEFILE
   1085 static char		pagefile_templ[PATH_MAX];
   1086 #endif
   1087 
   1088 /* Protects reserve-related data structures. */
   1089 static malloc_mutex_t	reserve_mtx;
   1090 
   1091 /*
   1092  * Bounds on acceptable reserve size, and current reserve size.  Reserve
   1093  * depletion may cause (reserve_cur < reserve_min).
   1094  */
   1095 static size_t		reserve_min;
   1096 static size_t		reserve_cur;
   1097 static size_t		reserve_max;
   1098 
   1099 /* List of registered callbacks. */
   1100 static ql_head(reserve_reg_t) reserve_regs;
   1101 
   1102 /*
   1103  * Condition notification sequence number, used to determine whether all
   1104  * registered callbacks have been notified of the most current condition.
   1105  */
   1106 static uint64_t		reserve_seq;
   1107 
   1108 /*
   1109  * Trees of chunks currently in the memory reserve.  Depending on function,
   1110  * different tree orderings are needed, which is why there are two trees with
   1111  * the same contents.
   1112  */
   1113 static extent_tree_t	reserve_chunks_szad;
   1114 static extent_tree_t	reserve_chunks_ad;
   1115 
   1116 /****************************/
   1117 /*
   1118  * base (internal allocation).
   1119  */
   1120 
   1121 /*
   1122  * Current pages that are being used for internal memory allocations.  These
   1123  * pages are carved up in cacheline-size quanta, so that there is no chance of
   1124  * false cache line sharing.
   1125  */
   1126 static void		*base_pages;
   1127 static void		*base_next_addr;
   1128 #ifdef MALLOC_DECOMMIT
   1129 static void		*base_next_decommitted;
   1130 #endif
   1131 static void		*base_past_addr; /* Addr immediately past base_pages. */
   1132 static extent_node_t	*base_nodes;
   1133 static reserve_reg_t	*base_reserve_regs;
   1134 static malloc_mutex_t	base_mtx;
   1135 #ifdef MALLOC_STATS
   1136 static size_t		base_mapped;
   1137 #endif
   1138 
   1139 /********/
   1140 /*
   1141  * Arenas.
   1142  */
   1143 
   1144 /*
   1145  * Arenas that are used to service external requests.  Not all elements of the
   1146  * arenas array are necessarily used; arenas are created lazily as needed.
   1147  */
   1148 static arena_t		**arenas;
   1149 static unsigned		narenas;
   1150 static unsigned		narenas_2pow;
   1151 #ifndef NO_TLS
   1152 #  ifdef MALLOC_BALANCE
   1153 static unsigned		narenas_2pow;
   1154 #  else
   1155 static unsigned		next_arena;
   1156 #  endif
   1157 #endif
   1158 #ifdef MOZ_MEMORY
   1159 static malloc_spinlock_t arenas_lock; /* Protects arenas initialization. */
   1160 #else
   1161 static pthread_mutex_t arenas_lock; /* Protects arenas initialization. */
   1162 #endif
   1163 
   1164 #ifndef NO_TLS
   1165 /*
   1166  * Map of pthread_self() --> arenas[???], used for selecting an arena to use
   1167  * for allocations.
   1168  */
   1169 #ifndef MOZ_MEMORY_WINDOWS
   1170 static __thread arena_t	*arenas_map;
   1171 #endif
   1172 #endif
   1173 
   1174 #ifdef MALLOC_STATS
   1175 /* Chunk statistics. */
   1176 static chunk_stats_t	stats_chunks;
   1177 #endif
   1178 
   1179 /*******************************/
   1180 /*
   1181  * Runtime configuration options.
   1182  */
   1183 const char	*_malloc_options;
   1184 
   1185 #ifndef MALLOC_PRODUCTION
   1186 static bool	opt_abort = true;
   1187 #ifdef MALLOC_FILL
   1188 static bool	opt_junk = true;
   1189 #endif
   1190 #else
   1191 static bool	opt_abort = false;
   1192 #ifdef MALLOC_FILL
   1193 static bool	opt_junk = false;
   1194 #endif
   1195 #endif
   1196 static size_t	opt_dirty_max = DIRTY_MAX_DEFAULT;
   1197 #ifdef MALLOC_BALANCE
   1198 static uint64_t	opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT;
   1199 #endif
   1200 static bool	opt_print_stats = false;
   1201 static size_t	opt_quantum_2pow = QUANTUM_2POW_MIN;
   1202 static size_t	opt_small_max_2pow = SMALL_MAX_2POW_DEFAULT;
   1203 static size_t	opt_chunk_2pow = CHUNK_2POW_DEFAULT;
   1204 static int	opt_reserve_min_lshift = 0;
   1205 static int	opt_reserve_range_lshift = 0;
   1206 #ifdef MALLOC_PAGEFILE
   1207 static bool	opt_pagefile = false;
   1208 #endif
   1209 #ifdef MALLOC_UTRACE
   1210 static bool	opt_utrace = false;
   1211 #endif
   1212 #ifdef MALLOC_SYSV
   1213 static bool	opt_sysv = false;
   1214 #endif
   1215 #ifdef MALLOC_XMALLOC
   1216 static bool	opt_xmalloc = false;
   1217 #endif
   1218 #ifdef MALLOC_FILL
   1219 static bool	opt_zero = false;
   1220 #endif
   1221 static int	opt_narenas_lshift = 0;
   1222 
   1223 #ifdef MALLOC_UTRACE
   1224 typedef struct {
   1225 	void	*p;
   1226 	size_t	s;
   1227 	void	*r;
   1228 } malloc_utrace_t;
   1229 
   1230 #define	UTRACE(a, b, c)							\
   1231 	if (opt_utrace) {						\
   1232 		malloc_utrace_t ut;					\
   1233 		ut.p = (a);						\
   1234 		ut.s = (b);						\
   1235 		ut.r = (c);						\
   1236 		utrace(&ut, sizeof(ut));				\
   1237 	}
   1238 #else
   1239 #define	UTRACE(a, b, c)
   1240 #endif
   1241 
   1242 /******************************************************************************/
   1243 /*
   1244  * Begin function prototypes for non-inline static functions.
   1245  */
   1246 
   1247 static char	*umax2s(uintmax_t x, char *s);
   1248 static bool	malloc_mutex_init(malloc_mutex_t *mutex);
   1249 static bool	malloc_spin_init(malloc_spinlock_t *lock);
   1250 static void	wrtmessage(const char *p1, const char *p2, const char *p3,
   1251 		const char *p4);
   1252 #ifdef MALLOC_STATS
   1253 #ifdef MOZ_MEMORY_DARWIN
   1254 /* Avoid namespace collision with OS X's malloc APIs. */
   1255 #define malloc_printf moz_malloc_printf
   1256 #endif
   1257 static void	malloc_printf(const char *format, ...);
   1258 #endif
   1259 static bool	base_pages_alloc_mmap(size_t minsize);
   1260 static bool	base_pages_alloc(size_t minsize);
   1261 static void	*base_alloc(size_t size);
   1262 static void	*base_calloc(size_t number, size_t size);
   1263 static extent_node_t *base_node_alloc(void);
   1264 static void	base_node_dealloc(extent_node_t *node);
   1265 static reserve_reg_t *base_reserve_reg_alloc(void);
   1266 static void	base_reserve_reg_dealloc(reserve_reg_t *reg);
   1267 #ifdef MALLOC_STATS
   1268 static void	stats_print(arena_t *arena);
   1269 #endif
   1270 static void	*pages_map(void *addr, size_t size, int pfd);
   1271 static void	pages_unmap(void *addr, size_t size);
   1272 static void	*chunk_alloc_mmap(size_t size, bool pagefile);
   1273 #ifdef MALLOC_PAGEFILE
   1274 static int	pagefile_init(size_t size);
   1275 static void	pagefile_close(int pfd);
   1276 #endif
   1277 static void	*chunk_recycle_reserve(size_t size, bool zero);
   1278 static void	*chunk_alloc(size_t size, bool zero, bool pagefile);
   1279 static extent_node_t *chunk_dealloc_reserve(void *chunk, size_t size);
   1280 static void	chunk_dealloc_mmap(void *chunk, size_t size);
   1281 static void	chunk_dealloc(void *chunk, size_t size);
   1282 #ifndef NO_TLS
   1283 static arena_t	*choose_arena_hard(void);
   1284 #endif
   1285 static void	arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
   1286     bool large, bool zero);
   1287 static void arena_chunk_init(arena_t *arena, arena_chunk_t *chunk);
   1288 static void	arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
   1289 static arena_run_t *arena_run_alloc(arena_t *arena, arena_bin_t *bin,
   1290     size_t size, bool large, bool zero);
   1291 static void	arena_purge(arena_t *arena);
   1292 static void	arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty);
   1293 static void	arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
   1294     arena_run_t *run, size_t oldsize, size_t newsize);
   1295 static void	arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
   1296     arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
   1297 static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
   1298 static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
   1299 static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size);
   1300 #ifdef MALLOC_BALANCE
   1301 static void	arena_lock_balance_hard(arena_t *arena);
   1302 #endif
   1303 static void	*arena_malloc_large(arena_t *arena, size_t size, bool zero);
   1304 static void	*arena_palloc(arena_t *arena, size_t alignment, size_t size,
   1305     size_t alloc_size);
   1306 static size_t	arena_salloc(const void *ptr);
   1307 static void	arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk,
   1308     void *ptr);
   1309 static void	arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
   1310     void *ptr, size_t size, size_t oldsize);
   1311 static bool	arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
   1312     void *ptr, size_t size, size_t oldsize);
   1313 static bool	arena_ralloc_large(void *ptr, size_t size, size_t oldsize);
   1314 static void	*arena_ralloc(void *ptr, size_t size, size_t oldsize);
   1315 static bool	arena_new(arena_t *arena);
   1316 static arena_t	*arenas_extend(unsigned ind);
   1317 static void	*huge_malloc(size_t size, bool zero);
   1318 static void	*huge_palloc(size_t alignment, size_t size);
   1319 static void	*huge_ralloc(void *ptr, size_t size, size_t oldsize);
   1320 static void	huge_dalloc(void *ptr);
   1321 static void	malloc_print_stats(void);
   1322 #ifndef MOZ_MEMORY_WINDOWS
   1323 static
   1324 #endif
   1325 bool		malloc_init_hard(void);
   1326 static void	reserve_shrink(void);
   1327 static uint64_t	reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq);
   1328 static uint64_t	reserve_crit(size_t size, const char *fname, uint64_t seq);
   1329 static void	reserve_fail(size_t size, const char *fname);
   1330 
   1331 void		_malloc_prefork(void);
   1332 void		_malloc_postfork(void);
   1333 
   1334 /*
   1335  * End function prototypes.
   1336  */
   1337 /******************************************************************************/
   1338 
   1339 /*
   1340  * umax2s() provides minimal integer printing functionality, which is
   1341  * especially useful for situations where allocation in vsnprintf() calls would
   1342  * potentially cause deadlock.
   1343  */
   1344 #define	UMAX2S_BUFSIZE	21
   1345 static char *
   1346 umax2s(uintmax_t x, char *s)
   1347 {
   1348 	unsigned i;
   1349 
   1350 	i = UMAX2S_BUFSIZE - 1;
   1351 	s[i] = '\0';
   1352 	do {
   1353 		i--;
   1354 		s[i] = "0123456789"[x % 10];
   1355 		x /= 10;
   1356 	} while (x > 0);
   1357 
   1358 	return (&s[i]);
   1359 }
   1360 
   1361 static void
   1362 wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
   1363 {
   1364 #ifdef MOZ_MEMORY_WINCE
   1365        wchar_t buf[1024];
   1366 #define WRT_PRINT(s) \
   1367        MultiByteToWideChar(CP_ACP, 0, s, -1, buf, 1024); \
   1368        OutputDebugStringW(buf)
   1369 
   1370        WRT_PRINT(p1);
   1371        WRT_PRINT(p2);
   1372        WRT_PRINT(p3);
   1373        WRT_PRINT(p4);
   1374 #else
   1375 #if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_WINDOWS)
   1376 #define	_write	write
   1377 #endif
   1378 	_write(STDERR_FILENO, p1, (unsigned int) strlen(p1));
   1379 	_write(STDERR_FILENO, p2, (unsigned int) strlen(p2));
   1380 	_write(STDERR_FILENO, p3, (unsigned int) strlen(p3));
   1381 	_write(STDERR_FILENO, p4, (unsigned int) strlen(p4));
   1382 #endif
   1383 
   1384 }
   1385 
   1386 #define _malloc_message malloc_message
   1387 
   1388 void	(*_malloc_message)(const char *p1, const char *p2, const char *p3,
   1389 	    const char *p4) = wrtmessage;
   1390 
   1391 #ifdef MALLOC_DEBUG
   1392 #  define assert(e) do {						\
   1393 	if (!(e)) {							\
   1394 		char line_buf[UMAX2S_BUFSIZE];				\
   1395 		_malloc_message(__FILE__, ":", umax2s(__LINE__,		\
   1396 		    line_buf), ": Failed assertion: ");			\
   1397 		_malloc_message("\"", #e, "\"\n", "");			\
   1398 		abort();						\
   1399 	}								\
   1400 } while (0)
   1401 #else
   1402 #define assert(e)
   1403 #endif
   1404 
   1405 /******************************************************************************/
   1406 /*
   1407  * Begin mutex.  We can't use normal pthread mutexes in all places, because
   1408  * they require malloc()ed memory, which causes bootstrapping issues in some
   1409  * cases.
   1410  */
   1411 
   1412 static bool
   1413 malloc_mutex_init(malloc_mutex_t *mutex)
   1414 {
   1415 #if defined(MOZ_MEMORY_WINCE)
   1416 	InitializeCriticalSection(mutex);
   1417 #elif defined(MOZ_MEMORY_WINDOWS)
   1418 	if (__isthreaded)
   1419 		if (! __crtInitCritSecAndSpinCount(mutex, _CRT_SPINCOUNT))
   1420 			return (true);
   1421 #elif defined(MOZ_MEMORY_DARWIN)
   1422 	mutex->lock = OS_SPINLOCK_INIT;
   1423 #elif defined(MOZ_MEMORY_LINUX)
   1424 	pthread_mutexattr_t attr;
   1425 	if (pthread_mutexattr_init(&attr) != 0)
   1426 		return (true);
   1427 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
   1428 	if (pthread_mutex_init(mutex, &attr) != 0) {
   1429 		pthread_mutexattr_destroy(&attr);
   1430 		return (true);
   1431 	}
   1432 	pthread_mutexattr_destroy(&attr);
   1433 #elif defined(MOZ_MEMORY)
   1434 	if (pthread_mutex_init(mutex, NULL) != 0)
   1435 		return (true);
   1436 #else
   1437 	static const spinlock_t lock = _SPINLOCK_INITIALIZER;
   1438 
   1439 	mutex->lock = lock;
   1440 #endif
   1441 	return (false);
   1442 }
   1443 
   1444 static inline void
   1445 malloc_mutex_lock(malloc_mutex_t *mutex)
   1446 {
   1447 
   1448 #if defined(MOZ_MEMORY_WINDOWS)
   1449 	EnterCriticalSection(mutex);
   1450 #elif defined(MOZ_MEMORY_DARWIN)
   1451 	OSSpinLockLock(&mutex->lock);
   1452 #elif defined(MOZ_MEMORY)
   1453 	pthread_mutex_lock(mutex);
   1454 #else
   1455 	if (__isthreaded)
   1456 		_SPINLOCK(&mutex->lock);
   1457 #endif
   1458 }
   1459 
   1460 static inline void
   1461 malloc_mutex_unlock(malloc_mutex_t *mutex)
   1462 {
   1463 
   1464 #if defined(MOZ_MEMORY_WINDOWS)
   1465 	LeaveCriticalSection(mutex);
   1466 #elif defined(MOZ_MEMORY_DARWIN)
   1467 	OSSpinLockUnlock(&mutex->lock);
   1468 #elif defined(MOZ_MEMORY)
   1469 	pthread_mutex_unlock(mutex);
   1470 #else
   1471 	if (__isthreaded)
   1472 		_SPINUNLOCK(&mutex->lock);
   1473 #endif
   1474 }
   1475 
   1476 static bool
   1477 malloc_spin_init(malloc_spinlock_t *lock)
   1478 {
   1479 #if defined(MOZ_MEMORY_WINCE)
   1480 	InitializeCriticalSection(lock);
   1481 #elif defined(MOZ_MEMORY_WINDOWS)
   1482 	if (__isthreaded)
   1483 		if (! __crtInitCritSecAndSpinCount(lock, _CRT_SPINCOUNT))
   1484 			return (true);
   1485 #elif defined(MOZ_MEMORY_DARWIN)
   1486 	lock->lock = OS_SPINLOCK_INIT;
   1487 #elif defined(MOZ_MEMORY_LINUX)
   1488 	pthread_mutexattr_t attr;
   1489 	if (pthread_mutexattr_init(&attr) != 0)
   1490 		return (true);
   1491 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
   1492 	if (pthread_mutex_init(lock, &attr) != 0) {
   1493 		pthread_mutexattr_destroy(&attr);
   1494 		return (true);
   1495 	}
   1496 	pthread_mutexattr_destroy(&attr);
   1497 #elif defined(MOZ_MEMORY)
   1498 	if (pthread_mutex_init(lock, NULL) != 0)
   1499 		return (true);
   1500 #else
   1501 	lock->lock = _SPINLOCK_INITIALIZER;
   1502 #endif
   1503 	return (false);
   1504 }
   1505 
   1506 static inline void
   1507 malloc_spin_lock(malloc_spinlock_t *lock)
   1508 {
   1509 
   1510 #if defined(MOZ_MEMORY_WINDOWS)
   1511 	EnterCriticalSection(lock);
   1512 #elif defined(MOZ_MEMORY_DARWIN)
   1513 	OSSpinLockLock(&lock->lock);
   1514 #elif defined(MOZ_MEMORY)
   1515 	pthread_mutex_lock(lock);
   1516 #else
   1517 	if (__isthreaded)
   1518 		_SPINLOCK(&lock->lock);
   1519 #endif
   1520 }
   1521 
   1522 static inline void
   1523 malloc_spin_unlock(malloc_spinlock_t *lock)
   1524 {
   1525 #if defined(MOZ_MEMORY_WINDOWS)
   1526 	LeaveCriticalSection(lock);
   1527 #elif defined(MOZ_MEMORY_DARWIN)
   1528 	OSSpinLockUnlock(&lock->lock);
   1529 #elif defined(MOZ_MEMORY)
   1530 	pthread_mutex_unlock(lock);
   1531 #else
   1532 	if (__isthreaded)
   1533 		_SPINUNLOCK(&lock->lock);
   1534 #endif
   1535 }
   1536 
   1537 /*
   1538  * End mutex.
   1539  */
   1540 /******************************************************************************/
   1541 /*
   1542  * Begin spin lock.  Spin locks here are actually adaptive mutexes that block
   1543  * after a period of spinning, because unbounded spinning would allow for
   1544  * priority inversion.
   1545  */
   1546 
   1547 #if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_DARWIN)
   1548 #  define	malloc_spin_init	malloc_mutex_init
   1549 #  define	malloc_spin_lock	malloc_mutex_lock
   1550 #  define	malloc_spin_unlock	malloc_mutex_unlock
   1551 #endif
   1552 
   1553 #ifndef MOZ_MEMORY
   1554 /*
   1555  * We use an unpublished interface to initialize pthread mutexes with an
   1556  * allocation callback, in order to avoid infinite recursion.
   1557  */
   1558 int	_pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
   1559     void *(calloc_cb)(size_t, size_t));
   1560 
   1561 __weak_reference(_pthread_mutex_init_calloc_cb_stub,
   1562     _pthread_mutex_init_calloc_cb);
   1563 
   1564 int
   1565 _pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex,
   1566     void *(calloc_cb)(size_t, size_t))
   1567 {
   1568 
   1569 	return (0);
   1570 }
   1571 
   1572 static bool
   1573 malloc_spin_init(pthread_mutex_t *lock)
   1574 {
   1575 
   1576 	if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0)
   1577 		return (true);
   1578 
   1579 	return (false);
   1580 }
   1581 
   1582 static inline unsigned
   1583 malloc_spin_lock(pthread_mutex_t *lock)
   1584 {
   1585 	unsigned ret = 0;
   1586 
   1587 	if (__isthreaded) {
   1588 		if (_pthread_mutex_trylock(lock) != 0) {
   1589 			unsigned i;
   1590 			volatile unsigned j;
   1591 
   1592 			/* Exponentially back off. */
   1593 			for (i = 1; i <= SPIN_LIMIT_2POW; i++) {
   1594 				for (j = 0; j < (1U << i); j++)
   1595 					ret++;
   1596 
   1597 				CPU_SPINWAIT;
   1598 				if (_pthread_mutex_trylock(lock) == 0)
   1599 					return (ret);
   1600 			}
   1601 
   1602 			/*
   1603 			 * Spinning failed.  Block until the lock becomes
   1604 			 * available, in order to avoid indefinite priority
   1605 			 * inversion.
   1606 			 */
   1607 			_pthread_mutex_lock(lock);
   1608 			assert((ret << BLOCK_COST_2POW) != 0);
   1609 			return (ret << BLOCK_COST_2POW);
   1610 		}
   1611 	}
   1612 
   1613 	return (ret);
   1614 }
   1615 
   1616 static inline void
   1617 malloc_spin_unlock(pthread_mutex_t *lock)
   1618 {
   1619 
   1620 	if (__isthreaded)
   1621 		_pthread_mutex_unlock(lock);
   1622 }
   1623 #endif
   1624 
   1625 /*
   1626  * End spin lock.
   1627  */
   1628 /******************************************************************************/
   1629 /*
   1630  * Begin Utility functions/macros.
   1631  */
   1632 
   1633 /* Return the chunk address for allocation address a. */
   1634 #define	CHUNK_ADDR2BASE(a)						\
   1635 	((void *)((uintptr_t)(a) & ~chunksize_mask))
   1636 
   1637 /* Return the chunk offset of address a. */
   1638 #define	CHUNK_ADDR2OFFSET(a)						\
   1639 	((size_t)((uintptr_t)(a) & chunksize_mask))
   1640 
   1641 /* Return the smallest chunk multiple that is >= s. */
   1642 #define	CHUNK_CEILING(s)						\
   1643 	(((s) + chunksize_mask) & ~chunksize_mask)
   1644 
   1645 /* Return the smallest cacheline multiple that is >= s. */
   1646 #define	CACHELINE_CEILING(s)						\
   1647 	(((s) + (CACHELINE - 1)) & ~(CACHELINE - 1))
   1648 
   1649 /* Return the smallest quantum multiple that is >= a. */
   1650 #define	QUANTUM_CEILING(a)						\
   1651 	(((a) + quantum_mask) & ~quantum_mask)
   1652 
   1653 /* Return the smallest pagesize multiple that is >= s. */
   1654 #define	PAGE_CEILING(s)							\
   1655 	(((s) + pagesize_mask) & ~pagesize_mask)
   1656 
   1657 /* Compute the smallest power of 2 that is >= x. */
   1658 static inline size_t
   1659 pow2_ceil(size_t x)
   1660 {
   1661 
   1662 	x--;
   1663 	x |= x >> 1;
   1664 	x |= x >> 2;
   1665 	x |= x >> 4;
   1666 	x |= x >> 8;
   1667 	x |= x >> 16;
   1668 #if (SIZEOF_PTR == 8)
   1669 	x |= x >> 32;
   1670 #endif
   1671 	x++;
   1672 	return (x);
   1673 }
   1674 
   1675 #ifdef MALLOC_BALANCE
   1676 /*
   1677  * Use a simple linear congruential pseudo-random number generator:
   1678  *
   1679  *   prn(y) = (a*x + c) % m
   1680  *
   1681  * where the following constants ensure maximal period:
   1682  *
   1683  *   a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.
   1684  *   c == Odd number (relatively prime to 2^n).
   1685  *   m == 2^32
   1686  *
   1687  * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.
   1688  *
   1689  * This choice of m has the disadvantage that the quality of the bits is
   1690  * proportional to bit position.  For example. the lowest bit has a cycle of 2,
   1691  * the next has a cycle of 4, etc.  For this reason, we prefer to use the upper
   1692  * bits.
   1693  */
   1694 #  define PRN_DEFINE(suffix, var, a, c)					\
   1695 static inline void							\
   1696 sprn_##suffix(uint32_t seed)						\
   1697 {									\
   1698 	var = seed;							\
   1699 }									\
   1700 									\
   1701 static inline uint32_t							\
   1702 prn_##suffix(uint32_t lg_range)						\
   1703 {									\
   1704 	uint32_t ret, x;						\
   1705 									\
   1706 	assert(lg_range > 0);						\
   1707 	assert(lg_range <= 32);						\
   1708 									\
   1709 	x = (var * (a)) + (c);						\
   1710 	var = x;							\
   1711 	ret = x >> (32 - lg_range);					\
   1712 									\
   1713 	return (ret);							\
   1714 }
   1715 #  define SPRN(suffix, seed)	sprn_##suffix(seed)
   1716 #  define PRN(suffix, lg_range)	prn_##suffix(lg_range)
   1717 #endif
   1718 
   1719 #ifdef MALLOC_BALANCE
   1720 /* Define the PRNG used for arena assignment. */
   1721 static __thread uint32_t balance_x;
   1722 PRN_DEFINE(balance, balance_x, 1297, 1301)
   1723 #endif
   1724 
   1725 #ifdef MALLOC_UTRACE
   1726 static int
   1727 utrace(const void *addr, size_t len)
   1728 {
   1729 	malloc_utrace_t *ut = (malloc_utrace_t *)addr;
   1730 
   1731 	assert(len == sizeof(malloc_utrace_t));
   1732 
   1733 	if (ut->p == NULL && ut->s == 0 && ut->r == NULL)
   1734 		malloc_printf("%d x USER malloc_init()\n", getpid());
   1735 	else if (ut->p == NULL && ut->r != NULL) {
   1736 		malloc_printf("%d x USER %p = malloc(%zu)\n", getpid(), ut->r,
   1737 		    ut->s);
   1738 	} else if (ut->p != NULL && ut->r != NULL) {
   1739 		malloc_printf("%d x USER %p = realloc(%p, %zu)\n", getpid(),
   1740 		    ut->r, ut->p, ut->s);
   1741 	} else
   1742 		malloc_printf("%d x USER free(%p)\n", getpid(), ut->p);
   1743 
   1744 	return (0);
   1745 }
   1746 #endif
   1747 
   1748 static inline const char *
   1749 _getprogname(void)
   1750 {
   1751 
   1752 	return ("<jemalloc>");
   1753 }
   1754 
   1755 #ifdef MALLOC_STATS
   1756 /*
   1757  * Print to stderr in such a way as to (hopefully) avoid memory allocation.
   1758  */
   1759 static void
   1760 malloc_printf(const char *format, ...)
   1761 {
   1762 #ifndef WINCE
   1763 	char buf[4096];
   1764 	va_list ap;
   1765 
   1766 	va_start(ap, format);
   1767 	vsnprintf(buf, sizeof(buf), format, ap);
   1768 	va_end(ap);
   1769 	_malloc_message(buf, "", "", "");
   1770 #endif
   1771 }
   1772 #endif
   1773 
   1774 /******************************************************************************/
   1775 
   1776 #ifdef MALLOC_DECOMMIT
   1777 static inline void
   1778 pages_decommit(void *addr, size_t size)
   1779 {
   1780 
   1781 #ifdef MOZ_MEMORY_WINDOWS
   1782 	VirtualFree(addr, size, MEM_DECOMMIT);
   1783 #else
   1784 	if (mmap(addr, size, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1,
   1785 	    0) == MAP_FAILED)
   1786 		abort();
   1787 #endif
   1788 }
   1789 
   1790 static inline void
   1791 pages_commit(void *addr, size_t size)
   1792 {
   1793 
   1794 #  ifdef MOZ_MEMORY_WINDOWS
   1795 	VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE);
   1796 #  else
   1797 	if (mmap(addr, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE |
   1798 	    MAP_ANON, -1, 0) == MAP_FAILED)
   1799 		abort();
   1800 #  endif
   1801 }
   1802 #endif
   1803 
   1804 static bool
   1805 base_pages_alloc_mmap(size_t minsize)
   1806 {
   1807 	bool ret;
   1808 	size_t csize;
   1809 #ifdef MALLOC_DECOMMIT
   1810 	size_t pminsize;
   1811 #endif
   1812 	int pfd;
   1813 
   1814 	assert(minsize != 0);
   1815 	csize = CHUNK_CEILING(minsize);
   1816 #ifdef MALLOC_PAGEFILE
   1817 	if (opt_pagefile) {
   1818 		pfd = pagefile_init(csize);
   1819 		if (pfd == -1)
   1820 			return (true);
   1821 	} else
   1822 #endif
   1823 		pfd = -1;
   1824 	base_pages = pages_map(NULL, csize, pfd);
   1825 	if (base_pages == NULL) {
   1826 		ret = true;
   1827 		goto RETURN;
   1828 	}
   1829 	base_next_addr = base_pages;
   1830 	base_past_addr = (void *)((uintptr_t)base_pages + csize);
   1831 #ifdef MALLOC_DECOMMIT
   1832 	/*
   1833 	 * Leave enough pages for minsize committed, since otherwise they would
   1834 	 * have to be immediately recommitted.
   1835 	 */
   1836 	pminsize = PAGE_CEILING(minsize);
   1837 	base_next_decommitted = (void *)((uintptr_t)base_pages + pminsize);
   1838 	if (pminsize < csize)
   1839 		pages_decommit(base_next_decommitted, csize - pminsize);
   1840 #endif
   1841 #ifdef MALLOC_STATS
   1842 	base_mapped += csize;
   1843 #endif
   1844 
   1845 	ret = false;
   1846 RETURN:
   1847 #ifdef MALLOC_PAGEFILE
   1848 	if (pfd != -1)
   1849 		pagefile_close(pfd);
   1850 #endif
   1851 	return (false);
   1852 }
   1853 
   1854 static bool
   1855 base_pages_alloc(size_t minsize)
   1856 {
   1857 
   1858 	if (base_pages_alloc_mmap(minsize) == false)
   1859 		return (false);
   1860 
   1861 	return (true);
   1862 }
   1863 
   1864 static void *
   1865 base_alloc(size_t size)
   1866 {
   1867 	void *ret;
   1868 	size_t csize;
   1869 
   1870 	/* Round size up to nearest multiple of the cacheline size. */
   1871 	csize = CACHELINE_CEILING(size);
   1872 
   1873 	malloc_mutex_lock(&base_mtx);
   1874 	/* Make sure there's enough space for the allocation. */
   1875 	if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
   1876 		if (base_pages_alloc(csize)) {
   1877 			malloc_mutex_unlock(&base_mtx);
   1878 			return (NULL);
   1879 		}
   1880 	}
   1881 	/* Allocate. */
   1882 	ret = base_next_addr;
   1883 	base_next_addr = (void *)((uintptr_t)base_next_addr + csize);
   1884 #ifdef MALLOC_DECOMMIT
   1885 	/* Make sure enough pages are committed for the new allocation. */
   1886 	if ((uintptr_t)base_next_addr > (uintptr_t)base_next_decommitted) {
   1887 		void *pbase_next_addr =
   1888 		    (void *)(PAGE_CEILING((uintptr_t)base_next_addr));
   1889 
   1890 		pages_commit(base_next_decommitted, (uintptr_t)pbase_next_addr -
   1891 		    (uintptr_t)base_next_decommitted);
   1892 		base_next_decommitted = pbase_next_addr;
   1893 	}
   1894 #endif
   1895 	malloc_mutex_unlock(&base_mtx);
   1896 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
   1897 
   1898 	return (ret);
   1899 }
   1900 
   1901 static void *
   1902 base_calloc(size_t number, size_t size)
   1903 {
   1904 	void *ret;
   1905 
   1906 	ret = base_alloc(number * size);
   1907 #ifdef MALLOC_VALGRIND
   1908 	if (ret != NULL) {
   1909 		VALGRIND_FREELIKE_BLOCK(ret, 0);
   1910 		VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, true);
   1911 	}
   1912 #endif
   1913 	memset(ret, 0, number * size);
   1914 
   1915 	return (ret);
   1916 }
   1917 
   1918 static extent_node_t *
   1919 base_node_alloc(void)
   1920 {
   1921 	extent_node_t *ret;
   1922 
   1923 	malloc_mutex_lock(&base_mtx);
   1924 	if (base_nodes != NULL) {
   1925 		ret = base_nodes;
   1926 		base_nodes = *(extent_node_t **)ret;
   1927 		VALGRIND_FREELIKE_BLOCK(ret, 0);
   1928 		VALGRIND_MALLOCLIKE_BLOCK(ret, sizeof(extent_node_t), 0, false);
   1929 		malloc_mutex_unlock(&base_mtx);
   1930 	} else {
   1931 		malloc_mutex_unlock(&base_mtx);
   1932 		ret = (extent_node_t *)base_alloc(sizeof(extent_node_t));
   1933 	}
   1934 
   1935 	return (ret);
   1936 }
   1937 
   1938 static void
   1939 base_node_dealloc(extent_node_t *node)
   1940 {
   1941 
   1942 	malloc_mutex_lock(&base_mtx);
   1943 	VALGRIND_FREELIKE_BLOCK(node, 0);
   1944 	VALGRIND_MALLOCLIKE_BLOCK(node, sizeof(extent_node_t *), 0, false);
   1945 	*(extent_node_t **)node = base_nodes;
   1946 	base_nodes = node;
   1947 	malloc_mutex_unlock(&base_mtx);
   1948 }
   1949 
   1950 static reserve_reg_t *
   1951 base_reserve_reg_alloc(void)
   1952 {
   1953 	reserve_reg_t *ret;
   1954 
   1955 	malloc_mutex_lock(&base_mtx);
   1956 	if (base_reserve_regs != NULL) {
   1957 		ret = base_reserve_regs;
   1958 		base_reserve_regs = *(reserve_reg_t **)ret;
   1959 		VALGRIND_FREELIKE_BLOCK(ret, 0);
   1960 		VALGRIND_MALLOCLIKE_BLOCK(ret, sizeof(reserve_reg_t), 0, false);
   1961 		malloc_mutex_unlock(&base_mtx);
   1962 	} else {
   1963 		malloc_mutex_unlock(&base_mtx);
   1964 		ret = (reserve_reg_t *)base_alloc(sizeof(reserve_reg_t));
   1965 	}
   1966 
   1967 	return (ret);
   1968 }
   1969 
   1970 static void
   1971 base_reserve_reg_dealloc(reserve_reg_t *reg)
   1972 {
   1973 
   1974 	malloc_mutex_lock(&base_mtx);
   1975 	VALGRIND_FREELIKE_BLOCK(reg, 0);
   1976 	VALGRIND_MALLOCLIKE_BLOCK(reg, sizeof(reserve_reg_t *), 0, false);
   1977 	*(reserve_reg_t **)reg = base_reserve_regs;
   1978 	base_reserve_regs = reg;
   1979 	malloc_mutex_unlock(&base_mtx);
   1980 }
   1981 
   1982 /******************************************************************************/
   1983 
   1984 #ifdef MALLOC_STATS
   1985 static void
   1986 stats_print(arena_t *arena)
   1987 {
   1988 	unsigned i, gap_start;
   1989 
   1990 #ifdef MOZ_MEMORY_WINDOWS
   1991 	malloc_printf("dirty: %Iu page%s dirty, %I64u sweep%s,"
   1992 	    " %I64u madvise%s, %I64u page%s purged\n",
   1993 	    arena->ndirty, arena->ndirty == 1 ? "" : "s",
   1994 	    arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s",
   1995 	    arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s",
   1996 	    arena->stats.purged, arena->stats.purged == 1 ? "" : "s");
   1997 #  ifdef MALLOC_DECOMMIT
   1998 	malloc_printf("decommit: %I64u decommit%s, %I64u commit%s,"
   1999 	    " %I64u page%s decommitted\n",
   2000 	    arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s",
   2001 	    arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s",
   2002 	    arena->stats.decommitted,
   2003 	    (arena->stats.decommitted == 1) ? "" : "s");
   2004 #  endif
   2005 
   2006 	malloc_printf("            allocated      nmalloc      ndalloc\n");
   2007 	malloc_printf("small:   %12Iu %12I64u %12I64u\n",
   2008 	    arena->stats.allocated_small, arena->stats.nmalloc_small,
   2009 	    arena->stats.ndalloc_small);
   2010 	malloc_printf("large:   %12Iu %12I64u %12I64u\n",
   2011 	    arena->stats.allocated_large, arena->stats.nmalloc_large,
   2012 	    arena->stats.ndalloc_large);
   2013 	malloc_printf("total:   %12Iu %12I64u %12I64u\n",
   2014 	    arena->stats.allocated_small + arena->stats.allocated_large,
   2015 	    arena->stats.nmalloc_small + arena->stats.nmalloc_large,
   2016 	    arena->stats.ndalloc_small + arena->stats.ndalloc_large);
   2017 	malloc_printf("mapped:  %12Iu\n", arena->stats.mapped);
   2018 #else
   2019 	malloc_printf("dirty: %zu page%s dirty, %llu sweep%s,"
   2020 	    " %llu madvise%s, %llu page%s purged\n",
   2021 	    arena->ndirty, arena->ndirty == 1 ? "" : "s",
   2022 	    arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s",
   2023 	    arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s",
   2024 	    arena->stats.purged, arena->stats.purged == 1 ? "" : "s");
   2025 #  ifdef MALLOC_DECOMMIT
   2026 	malloc_printf("decommit: %llu decommit%s, %llu commit%s,"
   2027 	    " %llu page%s decommitted\n",
   2028 	    arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s",
   2029 	    arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s",
   2030 	    arena->stats.decommitted,
   2031 	    (arena->stats.decommitted == 1) ? "" : "s");
   2032 #  endif
   2033 
   2034 	malloc_printf("            allocated      nmalloc      ndalloc\n");
   2035 	malloc_printf("small:   %12zu %12llu %12llu\n",
   2036 	    arena->stats.allocated_small, arena->stats.nmalloc_small,
   2037 	    arena->stats.ndalloc_small);
   2038 	malloc_printf("large:   %12zu %12llu %12llu\n",
   2039 	    arena->stats.allocated_large, arena->stats.nmalloc_large,
   2040 	    arena->stats.ndalloc_large);
   2041 	malloc_printf("total:   %12zu %12llu %12llu\n",
   2042 	    arena->stats.allocated_small + arena->stats.allocated_large,
   2043 	    arena->stats.nmalloc_small + arena->stats.nmalloc_large,
   2044 	    arena->stats.ndalloc_small + arena->stats.ndalloc_large);
   2045 	malloc_printf("mapped:  %12zu\n", arena->stats.mapped);
   2046 #endif
   2047 	malloc_printf("bins:     bin   size regs pgs  requests   newruns"
   2048 	    "    reruns maxruns curruns\n");
   2049 	for (i = 0, gap_start = UINT_MAX; i < ntbins + nqbins + nsbins; i++) {
   2050 		if (arena->bins[i].stats.nrequests == 0) {
   2051 			if (gap_start == UINT_MAX)
   2052 				gap_start = i;
   2053 		} else {
   2054 			if (gap_start != UINT_MAX) {
   2055 				if (i > gap_start + 1) {
   2056 					/* Gap of more than one size class. */
   2057 					malloc_printf("[%u..%u]\n",
   2058 					    gap_start, i - 1);
   2059 				} else {
   2060 					/* Gap of one size class. */
   2061 					malloc_printf("[%u]\n", gap_start);
   2062 				}
   2063 				gap_start = UINT_MAX;
   2064 			}
   2065 			malloc_printf(
   2066 #if defined(MOZ_MEMORY_WINDOWS)
   2067 			    "%13u %1s %4u %4u %3u %9I64u %9I64u"
   2068 			    " %9I64u %7u %7u\n",
   2069 #else
   2070 			    "%13u %1s %4u %4u %3u %9llu %9llu"
   2071 			    " %9llu %7lu %7lu\n",
   2072 #endif
   2073 			    i,
   2074 			    i < ntbins ? "T" : i < ntbins + nqbins ? "Q" : "S",
   2075 			    arena->bins[i].reg_size,
   2076 			    arena->bins[i].nregs,
   2077 			    arena->bins[i].run_size >> pagesize_2pow,
   2078 			    arena->bins[i].stats.nrequests,
   2079 			    arena->bins[i].stats.nruns,
   2080 			    arena->bins[i].stats.reruns,
   2081 			    arena->bins[i].stats.highruns,
   2082 			    arena->bins[i].stats.curruns);
   2083 		}
   2084 	}
   2085 	if (gap_start != UINT_MAX) {
   2086 		if (i > gap_start + 1) {
   2087 			/* Gap of more than one size class. */
   2088 			malloc_printf("[%u..%u]\n", gap_start, i - 1);
   2089 		} else {
   2090 			/* Gap of one size class. */
   2091 			malloc_printf("[%u]\n", gap_start);
   2092 		}
   2093 	}
   2094 }
   2095 #endif
   2096 
   2097 /*
   2098  * End Utility functions/macros.
   2099  */
   2100 /******************************************************************************/
   2101 /*
   2102  * Begin extent tree code.
   2103  */
   2104 
   2105 static inline int
   2106 extent_szad_comp(extent_node_t *a, extent_node_t *b)
   2107 {
   2108 	int ret;
   2109 	size_t a_size = a->size;
   2110 	size_t b_size = b->size;
   2111 
   2112 	ret = (a_size > b_size) - (a_size < b_size);
   2113 	if (ret == 0) {
   2114 		uintptr_t a_addr = (uintptr_t)a->addr;
   2115 		uintptr_t b_addr = (uintptr_t)b->addr;
   2116 
   2117 		ret = (a_addr > b_addr) - (a_addr < b_addr);
   2118 	}
   2119 
   2120 	return (ret);
   2121 }
   2122 
   2123 /* Wrap red-black tree macros in functions. */
   2124 rb_wrap(static, extent_tree_szad_, extent_tree_t, extent_node_t,
   2125     link_szad, extent_szad_comp)
   2126 
   2127 static inline int
   2128 extent_ad_comp(extent_node_t *a, extent_node_t *b)
   2129 {
   2130 	uintptr_t a_addr = (uintptr_t)a->addr;
   2131 	uintptr_t b_addr = (uintptr_t)b->addr;
   2132 
   2133 	return ((a_addr > b_addr) - (a_addr < b_addr));
   2134 }
   2135 
   2136 /* Wrap red-black tree macros in functions. */
   2137 rb_wrap(static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad,
   2138     extent_ad_comp)
   2139 
   2140 /*
   2141  * End extent tree code.
   2142  */
   2143 /******************************************************************************/
   2144 /*
   2145  * Begin chunk management functions.
   2146  */
   2147 
   2148 #ifdef MOZ_MEMORY_WINDOWS
   2149 #ifdef MOZ_MEMORY_WINCE
   2150 #define ALIGN_ADDR2OFFSET(al, ad) \
   2151 	((uintptr_t)ad & (al - 1))
   2152 static void *
   2153 pages_map_align(size_t size, int pfd, size_t alignment)
   2154 {
   2155 
   2156 	void *ret;
   2157 	int offset;
   2158 	if (size % alignment)
   2159 		size += (alignment - (size % alignment));
   2160 	assert(size >= alignment);
   2161 	ret = pages_map(NULL, size, pfd);
   2162 	offset = ALIGN_ADDR2OFFSET(alignment, ret);
   2163 	if (offset) {
   2164 		/* try to over allocate by the ammount we're offset */
   2165 		void *tmp;
   2166 		pages_unmap(ret, size);
   2167 		tmp = VirtualAlloc(NULL, size + alignment - offset,
   2168 					 MEM_RESERVE, PAGE_NOACCESS);
   2169 		if (offset == ALIGN_ADDR2OFFSET(alignment, tmp))
   2170 			ret = VirtualAlloc((void*)((intptr_t)tmp + alignment
   2171 						   - offset), size, MEM_COMMIT,
   2172 					   PAGE_READWRITE);
   2173 		else
   2174 			VirtualFree(tmp, 0, MEM_RELEASE);
   2175 		offset = ALIGN_ADDR2OFFSET(alignment, ret);
   2176 
   2177 
   2178 		if (offset) {
   2179 			/* over allocate to ensure we have an aligned region */
   2180 			ret = VirtualAlloc(NULL, size + alignment, MEM_RESERVE,
   2181 					   PAGE_NOACCESS);
   2182 			offset = ALIGN_ADDR2OFFSET(alignment, ret);
   2183 			ret = VirtualAlloc((void*)((intptr_t)ret +
   2184 						   alignment - offset),
   2185 					   size, MEM_COMMIT, PAGE_READWRITE);
   2186 		}
   2187 	}
   2188 	return (ret);
   2189 }
   2190 #endif
   2191 
   2192 static void *
   2193 pages_map(void *addr, size_t size, int pfd)
   2194 {
   2195 	void *ret = NULL;
   2196 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
   2197 	void *va_ret;
   2198 	assert(addr == NULL);
   2199 	va_ret = VirtualAlloc(addr, size, MEM_RESERVE, PAGE_NOACCESS);
   2200 	if (va_ret)
   2201 		ret = VirtualAlloc(va_ret, size, MEM_COMMIT, PAGE_READWRITE);
   2202 	assert(va_ret == ret);
   2203 #else
   2204 	ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,
   2205 	    PAGE_READWRITE);
   2206 #endif
   2207 	return (ret);
   2208 }
   2209 
   2210 static void
   2211 pages_unmap(void *addr, size_t size)
   2212 {
   2213 	if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
   2214 #if defined(MOZ_MEMORY_WINCE) && !defined(MOZ_MEMORY_WINCE6)
   2215 		if (GetLastError() == ERROR_INVALID_PARAMETER) {
   2216 			MEMORY_BASIC_INFORMATION info;
   2217 			VirtualQuery(addr, &info, sizeof(info));
   2218 			if (VirtualFree(info.AllocationBase, 0, MEM_RELEASE))
   2219 				return;
   2220 		}
   2221 #endif
   2222 		_malloc_message(_getprogname(),
   2223 		    ": (malloc) Error in VirtualFree()\n", "", "");
   2224 		if (opt_abort)
   2225 			abort();
   2226 	}
   2227 }
   2228 #elif (defined(MOZ_MEMORY_DARWIN))
   2229 static void *
   2230 pages_map(void *addr, size_t size, int pfd)
   2231 {
   2232 	void *ret;
   2233 	kern_return_t err;
   2234 	int flags;
   2235 
   2236 	if (addr != NULL) {
   2237 		ret = addr;
   2238 		flags = 0;
   2239 	} else
   2240 		flags = VM_FLAGS_ANYWHERE;
   2241 
   2242 	err = vm_allocate((vm_map_t)mach_task_self(), (vm_address_t *)&ret,
   2243 	    (vm_size_t)size, flags);
   2244 	if (err != KERN_SUCCESS)
   2245 		ret = NULL;
   2246 
   2247 	assert(ret == NULL || (addr == NULL && ret != addr)
   2248 	    || (addr != NULL && ret == addr));
   2249 	return (ret);
   2250 }
   2251 
   2252 static void
   2253 pages_unmap(void *addr, size_t size)
   2254 {
   2255 	kern_return_t err;
   2256 
   2257 	err = vm_deallocate((vm_map_t)mach_task_self(), (vm_address_t)addr,
   2258 	    (vm_size_t)size);
   2259 	if (err != KERN_SUCCESS) {
   2260 		malloc_message(_getprogname(),
   2261 		    ": (malloc) Error in vm_deallocate(): ",
   2262 		    mach_error_string(err), "\n");
   2263 		if (opt_abort)
   2264 			abort();
   2265 	}
   2266 }
   2267 
   2268 #define	VM_COPY_MIN (pagesize << 5)
   2269 static inline void
   2270 pages_copy(void *dest, const void *src, size_t n)
   2271 {
   2272 
   2273 	assert((void *)((uintptr_t)dest & ~pagesize_mask) == dest);
   2274 	assert(n >= VM_COPY_MIN);
   2275 	assert((void *)((uintptr_t)src & ~pagesize_mask) == src);
   2276 
   2277 	vm_copy(mach_task_self(), (vm_address_t)src, (vm_size_t)n,
   2278 	    (vm_address_t)dest);
   2279 }
   2280 #else /* MOZ_MEMORY_DARWIN */
   2281 #ifdef JEMALLOC_USES_MAP_ALIGN
   2282 static void *
   2283 pages_map_align(size_t size, int pfd, size_t alignment)
   2284 {
   2285 	void *ret;
   2286 
   2287 	/*
   2288 	 * We don't use MAP_FIXED here, because it can cause the *replacement*
   2289 	 * of existing mappings, and we only want to create new mappings.
   2290 	 */
   2291 #ifdef MALLOC_PAGEFILE
   2292 	if (pfd != -1) {
   2293 		ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
   2294 		    MAP_NOSYNC | MAP_ALIGN, pfd, 0);
   2295 	} else
   2296 #endif
   2297 	       {
   2298 		ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
   2299 		    MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0);
   2300 	}
   2301 	assert(ret != NULL);
   2302 
   2303 	if (ret == MAP_FAILED)
   2304 		ret = NULL;
   2305 	return (ret);
   2306 }
   2307 #endif
   2308 
   2309 static void *
   2310 pages_map(void *addr, size_t size, int pfd)
   2311 {
   2312 	void *ret;
   2313 
   2314 	/*
   2315 	 * We don't use MAP_FIXED here, because it can cause the *replacement*
   2316 	 * of existing mappings, and we only want to create new mappings.
   2317 	 */
   2318 #ifdef MALLOC_PAGEFILE
   2319 	if (pfd != -1) {
   2320 		ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
   2321 		    MAP_NOSYNC, pfd, 0);
   2322 	} else
   2323 #endif
   2324 	       {
   2325 		ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
   2326 		    MAP_ANON, -1, 0);
   2327 	}
   2328 	assert(ret != NULL);
   2329 
   2330 	if (ret == MAP_FAILED)
   2331 		ret = NULL;
   2332 	else if (addr != NULL && ret != addr) {
   2333 		/*
   2334 		 * We succeeded in mapping memory, but not in the right place.
   2335 		 */
   2336 		if (munmap(ret, size) == -1) {
   2337 			char buf[STRERROR_BUF];
   2338 
   2339 			strerror_r(errno, buf, sizeof(buf));
   2340 			_malloc_message(_getprogname(),
   2341 			    ": (malloc) Error in munmap(): ", buf, "\n");
   2342 			if (opt_abort)
   2343 				abort();
   2344 		}
   2345 		ret = NULL;
   2346 	}
   2347 
   2348 	assert(ret == NULL || (addr == NULL && ret != addr)
   2349 	    || (addr != NULL && ret == addr));
   2350 	return (ret);
   2351 }
   2352 
   2353 static void
   2354 pages_unmap(void *addr, size_t size)
   2355 {
   2356 
   2357 	if (munmap(addr, size) == -1) {
   2358 		char buf[STRERROR_BUF];
   2359 
   2360 		strerror_r(errno, buf, sizeof(buf));
   2361 		_malloc_message(_getprogname(),
   2362 		    ": (malloc) Error in munmap(): ", buf, "\n");
   2363 		if (opt_abort)
   2364 			abort();
   2365 	}
   2366 }
   2367 #endif
   2368 
   2369 #ifdef MALLOC_VALIDATE
   2370 static inline malloc_rtree_t *
   2371 malloc_rtree_new(unsigned bits)
   2372 {
   2373 	malloc_rtree_t *ret;
   2374 	unsigned bits_per_level, height, i;
   2375 
   2376 	bits_per_level = ffs(pow2_ceil((MALLOC_RTREE_NODESIZE /
   2377 	    sizeof(void *)))) - 1;
   2378 	height = bits / bits_per_level;
   2379 	if (height * bits_per_level != bits)
   2380 		height++;
   2381 	assert(height * bits_per_level >= bits);
   2382 
   2383 	ret = (malloc_rtree_t*)base_calloc(1, sizeof(malloc_rtree_t) + (sizeof(unsigned) *
   2384 	    (height - 1)));
   2385 	if (ret == NULL)
   2386 		return (NULL);
   2387 
   2388 	malloc_spin_init(&ret->lock);
   2389 	ret->height = height;
   2390 	if (bits_per_level * height > bits)
   2391 		ret->level2bits[0] = bits % bits_per_level;
   2392 	else
   2393 		ret->level2bits[0] = bits_per_level;
   2394 	for (i = 1; i < height; i++)
   2395 		ret->level2bits[i] = bits_per_level;
   2396 
   2397 	ret->root = (void**)base_calloc(1, sizeof(void *) << ret->level2bits[0]);
   2398 	if (ret->root == NULL) {
   2399 		/*
   2400 		 * We leak the rtree here, since there's no generic base
   2401 		 * deallocation.
   2402 		 */
   2403 		return (NULL);
   2404 	}
   2405 
   2406 	return (ret);
   2407 }
   2408 
   2409 /* The least significant bits of the key are ignored. */
   2410 static inline void *
   2411 malloc_rtree_get(malloc_rtree_t *rtree, uintptr_t key)
   2412 {
   2413 	void *ret;
   2414 	uintptr_t subkey;
   2415 	unsigned i, lshift, height, bits;
   2416 	void **node, **child;
   2417 
   2418 	malloc_spin_lock(&rtree->lock);
   2419 	for (i = lshift = 0, height = rtree->height, node = rtree->root;
   2420 	    i < height - 1;
   2421 	    i++, lshift += bits, node = child) {
   2422 		bits = rtree->level2bits[i];
   2423 		subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
   2424 		child = (void**)node[subkey];
   2425 		if (child == NULL) {
   2426 			malloc_spin_unlock(&rtree->lock);
   2427 			return (NULL);
   2428 		}
   2429 	}
   2430 
   2431 	/* node is a leaf, so it contains values rather than node pointers. */
   2432 	bits = rtree->level2bits[i];
   2433 	subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
   2434 	ret = node[subkey];
   2435 	malloc_spin_unlock(&rtree->lock);
   2436 
   2437 	return (ret);
   2438 }
   2439 
   2440 static inline bool
   2441 malloc_rtree_set(malloc_rtree_t *rtree, uintptr_t key, void *val)
   2442 {
   2443 	uintptr_t subkey;
   2444 	unsigned i, lshift, height, bits;
   2445 	void **node, **child;
   2446 
   2447 	malloc_spin_lock(&rtree->lock);
   2448 	for (i = lshift = 0, height = rtree->height, node = rtree->root;
   2449 	    i < height - 1;
   2450 	    i++, lshift += bits, node = child) {
   2451 		bits = rtree->level2bits[i];
   2452 		subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
   2453 		child = (void**)node[subkey];
   2454 		if (child == NULL) {
   2455 			child = (void**)base_calloc(1, sizeof(void *) <<
   2456 			    rtree->level2bits[i+1]);
   2457 			if (child == NULL) {
   2458 				malloc_spin_unlock(&rtree->lock);
   2459 				return (true);
   2460 			}
   2461 			node[subkey] = child;
   2462 		}
   2463 	}
   2464 
   2465 	/* node is a leaf, so it contains values rather than node pointers. */
   2466 	bits = rtree->level2bits[i];
   2467 	subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
   2468 	node[subkey] = val;
   2469 	malloc_spin_unlock(&rtree->lock);
   2470 
   2471 	return (false);
   2472 }
   2473 #endif
   2474 
   2475 static void *
   2476 chunk_alloc_mmap(size_t size, bool pagefile)
   2477 {
   2478 	void *ret;
   2479 #ifndef JEMALLOC_USES_MAP_ALIGN
   2480 	size_t offset;
   2481 #endif
   2482 	int pfd;
   2483 
   2484 #ifdef MALLOC_PAGEFILE
   2485 	if (opt_pagefile && pagefile) {
   2486 		pfd = pagefile_init(size);
   2487 		if (pfd == -1)
   2488 			return (NULL);
   2489 	} else
   2490 #endif
   2491 		pfd = -1;
   2492 
   2493 	/*
   2494 	 * Windows requires that there be a 1:1 mapping between VM
   2495 	 * allocation/deallocation operations.  Therefore, take care here to
   2496 	 * acquire the final result via one mapping operation.  This means
   2497 	 * unmapping any preliminary result that is not correctly aligned.
   2498 	 *
   2499 	 * The MALLOC_PAGEFILE code also benefits from this mapping algorithm,
   2500 	 * since it reduces the number of page files.
   2501 	 */
   2502 
   2503 #ifdef JEMALLOC_USES_MAP_ALIGN
   2504 	ret = pages_map_align(size, pfd, chunksize);
   2505 #else
   2506 	ret = pages_map(NULL, size, pfd);
   2507 	if (ret == NULL)
   2508 		goto RETURN;
   2509 
   2510 	offset = CHUNK_ADDR2OFFSET(ret);
   2511 	if (offset != 0) {
   2512 		/* Deallocate, then try to allocate at (ret + size - offset). */
   2513 		pages_unmap(ret, size);
   2514 		ret = pages_map((void *)((uintptr_t)ret + size - offset), size,
   2515 		    pfd);
   2516 		while (ret == NULL) {
   2517 			/*
   2518 			 * Over-allocate in order to map a memory region that
   2519 			 * is definitely large enough.
   2520 			 */
   2521 			ret = pages_map(NULL, size + chunksize, -1);
   2522 			if (ret == NULL)
   2523 				goto RETURN;
   2524 			/*
   2525 			 * Deallocate, then allocate the correct size, within
   2526 			 * the over-sized mapping.
   2527 			 */
   2528 			offset = CHUNK_ADDR2OFFSET(ret);
   2529 			pages_unmap(ret, size + chunksize);
   2530 			if (offset == 0)
   2531 				ret = pages_map(ret, size, pfd);
   2532 			else {
   2533 				ret = pages_map((void *)((uintptr_t)ret +
   2534 				    chunksize - offset), size, pfd);
   2535 			}
   2536 			/*
   2537 			 * Failure here indicates a race with another thread, so
   2538 			 * try again.
   2539 			 */
   2540 		}
   2541 	}
   2542 RETURN:
   2543 #endif
   2544 #ifdef MALLOC_PAGEFILE
   2545 	if (pfd != -1)
   2546 		pagefile_close(pfd);
   2547 #endif
   2548 #ifdef MALLOC_STATS
   2549 	if (ret != NULL)
   2550 		stats_chunks.nchunks += (size / chunksize);
   2551 #endif
   2552 	return (ret);
   2553 }
   2554 
   2555 #ifdef MALLOC_PAGEFILE
   2556 static int
   2557 pagefile_init(size_t size)
   2558 {
   2559 	int ret;
   2560 	size_t i;
   2561 	char pagefile_path[PATH_MAX];
   2562 	char zbuf[MALLOC_PAGEFILE_WRITE_SIZE];
   2563 
   2564 	/*
   2565 	 * Create a temporary file, then immediately unlink it so that it will
   2566 	 * not persist.
   2567 	 */
   2568 	strcpy(pagefile_path, pagefile_templ);
   2569 	ret = mkstemp(pagefile_path);
   2570 	if (ret == -1)
   2571 		return (ret);
   2572 	if (unlink(pagefile_path)) {
   2573 		char buf[STRERROR_BUF];
   2574 
   2575 		strerror_r(errno, buf, sizeof(buf));
   2576 		_malloc_message(_getprogname(), ": (malloc) Error in unlink(\"",
   2577 		    pagefile_path, "\"):");
   2578 		_malloc_message(buf, "\n", "", "");
   2579 		if (opt_abort)
   2580 			abort();
   2581 	}
   2582 
   2583 	/*
   2584 	 * Write sequential zeroes to the file in order to assure that disk
   2585 	 * space is committed, with minimal fragmentation.  It would be
   2586 	 * sufficient to write one zero per disk block, but that potentially
   2587 	 * results in more system calls, for no real gain.
   2588 	 */
   2589 	memset(zbuf, 0, sizeof(zbuf));
   2590 	for (i = 0; i < size; i += sizeof(zbuf)) {
   2591 		if (write(ret, zbuf, sizeof(zbuf)) != sizeof(zbuf)) {
   2592 			if (errno != ENOSPC) {
   2593 				char buf[STRERROR_BUF];
   2594 
   2595 				strerror_r(errno, buf, sizeof(buf));
   2596 				_malloc_message(_getprogname(),
   2597 				    ": (malloc) Error in write(): ", buf, "\n");
   2598 				if (opt_abort)
   2599 					abort();
   2600 			}
   2601 			pagefile_close(ret);
   2602 			return (-1);
   2603 		}
   2604 	}
   2605 
   2606 	return (ret);
   2607 }
   2608 
   2609 static void
   2610 pagefile_close(int pfd)
   2611 {
   2612 
   2613 	if (close(pfd)) {
   2614 		char buf[STRERROR_BUF];
   2615 
   2616 		strerror_r(errno, buf, sizeof(buf));
   2617 		_malloc_message(_getprogname(),
   2618 		    ": (malloc) Error in close(): ", buf, "\n");
   2619 		if (opt_abort)
   2620 			abort();
   2621 	}
   2622 }
   2623 #endif
   2624 
   2625 static void *
   2626 chunk_recycle_reserve(size_t size, bool zero)
   2627 {
   2628 	extent_node_t *node, key;
   2629 
   2630 #ifdef MALLOC_DECOMMIT
   2631 	if (size != chunksize)
   2632 		return (NULL);
   2633 #endif
   2634 
   2635 	key.addr = NULL;
   2636 	key.size = size;
   2637 	malloc_mutex_lock(&reserve_mtx);
   2638 	node = extent_tree_szad_nsearch(&reserve_chunks_szad, &key);
   2639 	if (node != NULL) {
   2640 		void *ret = node->addr;
   2641 
   2642 		/* Remove node from the tree. */
   2643 		extent_tree_szad_remove(&reserve_chunks_szad, node);
   2644 #ifndef MALLOC_DECOMMIT
   2645 		if (node->size == size) {
   2646 #else
   2647 			assert(node->size == size);
   2648 #endif
   2649 			extent_tree_ad_remove(&reserve_chunks_ad, node);
   2650 			base_node_dealloc(node);
   2651 #ifndef MALLOC_DECOMMIT
   2652 		} else {
   2653 			/*
   2654 			 * Insert the remainder of node's address range as a
   2655 			 * smaller chunk.  Its position within reserve_chunks_ad
   2656 			 * does not change.
   2657 			 */
   2658 			assert(node->size > size);
   2659 			node->addr = (void *)((uintptr_t)node->addr + size);
   2660 			node->size -= size;
   2661 			extent_tree_szad_insert(&reserve_chunks_szad, node);
   2662 		}
   2663 #endif
   2664 		reserve_cur -= size;
   2665 		/*
   2666 		 * Try to replenish the reserve if this allocation depleted it.
   2667 		 */
   2668 #ifndef MALLOC_DECOMMIT
   2669 		if (reserve_cur < reserve_min) {
   2670 			size_t diff = reserve_min - reserve_cur;
   2671 #else
   2672 		while (reserve_cur < reserve_min) {
   2673 #  define diff chunksize
   2674 #endif
   2675 			void *chunk;
   2676 
   2677 			malloc_mutex_unlock(&reserve_mtx);
   2678 			chunk = chunk_alloc_mmap(diff, true);
   2679 			malloc_mutex_lock(&reserve_mtx);
   2680 			if (chunk == NULL) {
   2681 				uint64_t seq = 0;
   2682 
   2683 				do {
   2684 					seq = reserve_notify(RESERVE_CND_LOW,
   2685 					    size, seq);
   2686 					if (seq == 0)
   2687 						goto MALLOC_OUT;
   2688 				} while (reserve_cur < reserve_min);
   2689 			} else {
   2690 				extent_node_t *node;
   2691 
   2692 				node = chunk_dealloc_reserve(chunk, diff);
   2693 				if (node == NULL) {
   2694 					uint64_t seq = 0;
   2695 
   2696 					pages_unmap(chunk, diff);
   2697 					do {
   2698 						seq = reserve_notify(
   2699 						    RESERVE_CND_LOW, size, seq);
   2700 						if (seq == 0)
   2701 							goto MALLOC_OUT;
   2702 					} while (reserve_cur < reserve_min);
   2703 				}
   2704 			}
   2705 		}
   2706 MALLOC_OUT:
   2707 		malloc_mutex_unlock(&reserve_mtx);
   2708 
   2709 #ifdef MALLOC_DECOMMIT
   2710 		pages_commit(ret, size);
   2711 #  undef diff
   2712 #else
   2713 		if (zero)
   2714 			memset(ret, 0, size);
   2715 #endif
   2716 		return (ret);
   2717 	}
   2718 	malloc_mutex_unlock(&reserve_mtx);
   2719 
   2720 	return (NULL);
   2721 }
   2722 
   2723 static void *
   2724 chunk_alloc(size_t size, bool zero, bool pagefile)
   2725 {
   2726 	void *ret;
   2727 
   2728 	assert(size != 0);
   2729 	assert((size & chunksize_mask) == 0);
   2730 
   2731 	ret = chunk_recycle_reserve(size, zero);
   2732 	if (ret != NULL)
   2733 		goto RETURN;
   2734 
   2735 	ret = chunk_alloc_mmap(size, pagefile);
   2736 	if (ret != NULL) {
   2737 		goto RETURN;
   2738 	}
   2739 
   2740 	/* All strategies for allocation failed. */
   2741 	ret = NULL;
   2742 RETURN:
   2743 #ifdef MALLOC_STATS
   2744 	if (ret != NULL)
   2745 		stats_chunks.curchunks += (size / chunksize);
   2746 	if (stats_chunks.curchunks > stats_chunks.highchunks)
   2747 		stats_chunks.highchunks = stats_chunks.curchunks;
   2748 #endif
   2749 
   2750 #ifdef MALLOC_VALIDATE
   2751 	if (ret != NULL) {
   2752 		if (malloc_rtree_set(chunk_rtree, (uintptr_t)ret, ret)) {
   2753 			chunk_dealloc(ret, size);
   2754 			return (NULL);
   2755 		}
   2756 	}
   2757 #endif
   2758 
   2759 	assert(CHUNK_ADDR2BASE(ret) == ret);
   2760 	return (ret);
   2761 }
   2762 
   2763 static extent_node_t *
   2764 chunk_dealloc_reserve(void *chunk, size_t size)
   2765 {
   2766 	extent_node_t *node;
   2767 
   2768 #ifdef MALLOC_DECOMMIT
   2769 	if (size != chunksize)
   2770 		return (NULL);
   2771 #else
   2772 	extent_node_t *prev, key;
   2773 
   2774 	key.addr = (void *)((uintptr_t)chunk + size);
   2775 	node = extent_tree_ad_nsearch(&reserve_chunks_ad, &key);
   2776 	/* Try to coalesce forward. */
   2777 	if (node != NULL && node->addr == key.addr) {
   2778 		/*
   2779 		 * Coalesce chunk with the following address range.  This does
   2780 		 * not change the position within reserve_chunks_ad, so only
   2781 		 * remove/insert from/into reserve_chunks_szad.
   2782 		 */
   2783 		extent_tree_szad_remove(&reserve_chunks_szad, node);
   2784 		node->addr = chunk;
   2785 		node->size += size;
   2786 		extent_tree_szad_insert(&reserve_chunks_szad, node);
   2787 	} else {
   2788 #endif
   2789 		/* Coalescing forward failed, so insert a new node. */
   2790 		node = base_node_alloc();
   2791 		if (node == NULL)
   2792 			return (NULL);
   2793 		node->addr = chunk;
   2794 		node->size = size;
   2795 		extent_tree_ad_insert(&reserve_chunks_ad, node);
   2796 		extent_tree_szad_insert(&reserve_chunks_szad, node);
   2797 #ifndef MALLOC_DECOMMIT
   2798 	}
   2799 
   2800 	/* Try to coalesce backward. */
   2801 	prev = extent_tree_ad_prev(&reserve_chunks_ad, node);
   2802 	if (prev != NULL && (void *)((uintptr_t)prev->addr + prev->size) ==
   2803 	    chunk) {
   2804 		/*
   2805 		 * Coalesce chunk with the previous address range.  This does
   2806 		 * not change the position within reserve_chunks_ad, so only
   2807 		 * remove/insert node from/into reserve_chunks_szad.
   2808 		 */
   2809 		extent_tree_szad_remove(&reserve_chunks_szad, prev);
   2810 		extent_tree_ad_remove(&reserve_chunks_ad, prev);
   2811 
   2812 		extent_tree_szad_remove(&reserve_chunks_szad, node);
   2813 		node->addr = prev->addr;
   2814 		node->size += prev->size;
   2815 		extent_tree_szad_insert(&reserve_chunks_szad, node);
   2816 
   2817 		base_node_dealloc(prev);
   2818 	}
   2819 #endif
   2820 
   2821 #ifdef MALLOC_DECOMMIT
   2822 	pages_decommit(chunk, size);
   2823 #else
   2824 	madvise(chunk, size, MADV_FREE);
   2825 #endif
   2826 
   2827 	reserve_cur += size;
   2828 	if (reserve_cur > reserve_max)
   2829 		reserve_shrink();
   2830 
   2831 	return (node);
   2832 }
   2833 
   2834 static void
   2835 chunk_dealloc_mmap(void *chunk, size_t size)
   2836 {
   2837 
   2838 	pages_unmap(chunk, size);
   2839 }
   2840 
   2841 static void
   2842 chunk_dealloc(void *chunk, size_t size)
   2843 {
   2844 	extent_node_t *node;
   2845 
   2846 	assert(chunk != NULL);
   2847 	assert(CHUNK_ADDR2BASE(chunk) == chunk);
   2848 	assert(size != 0);
   2849 	assert((size & chunksize_mask) == 0);
   2850 
   2851 #ifdef MALLOC_STATS
   2852 	stats_chunks.curchunks -= (size / chunksize);
   2853 #endif
   2854 #ifdef MALLOC_VALIDATE
   2855 	malloc_rtree_set(chunk_rtree, (uintptr_t)chunk, NULL);
   2856 #endif
   2857 
   2858 	/* Try to merge chunk into the reserve. */
   2859 	malloc_mutex_lock(&reserve_mtx);
   2860 	node = chunk_dealloc_reserve(chunk, size);
   2861 	malloc_mutex_unlock(&reserve_mtx);
   2862 	if (node == NULL)
   2863 		chunk_dealloc_mmap(chunk, size);
   2864 }
   2865 
   2866 /*
   2867  * End chunk management functions.
   2868  */
   2869 /******************************************************************************/
   2870 /*
   2871  * Begin arena.
   2872  */
   2873 
   2874 /*
   2875  * Choose an arena based on a per-thread value (fast-path code, calls slow-path
   2876  * code if necessary).
   2877  */
   2878 static inline arena_t *
   2879 choose_arena(void)
   2880 {
   2881 	arena_t *ret;
   2882 
   2883 	/*
   2884 	 * We can only use TLS if this is a PIC library, since for the static
   2885 	 * library version, libc's malloc is used by TLS allocation, which
   2886 	 * introduces a bootstrapping issue.
   2887 	 */
   2888 #ifndef NO_TLS
   2889 	if (__isthreaded == false) {
   2890 	    /* Avoid the overhead of TLS for single-threaded operation. */
   2891 	    return (arenas[0]);
   2892 	}
   2893 
   2894 #  ifdef MOZ_MEMORY_WINDOWS
   2895 	ret = (arena_t*)TlsGetValue(tlsIndex);
   2896 #  else
   2897 	ret = arenas_map;
   2898 #  endif
   2899 
   2900 	if (ret == NULL) {
   2901 		ret = choose_arena_hard();
   2902 		assert(ret != NULL);
   2903 	}
   2904 #else
   2905 	if (__isthreaded && narenas > 1) {
   2906 		unsigned long ind;
   2907 
   2908 		/*
   2909 		 * Hash _pthread_self() to one of the arenas.  There is a prime
   2910 		 * number of arenas, so this has a reasonable chance of
   2911 		 * working.  Even so, the hashing can be easily thwarted by
   2912 		 * inconvenient _pthread_self() values.  Without specific
   2913 		 * knowledge of how _pthread_self() calculates values, we can't
   2914 		 * easily do much better than this.
   2915 		 */
   2916 		ind = (unsigned long) _pthread_self() % narenas;
   2917 
   2918 		/*
   2919 		 * Optimistially assume that arenas[ind] has been initialized.
   2920 		 * At worst, we find out that some other thread has already
   2921 		 * done so, after acquiring the lock in preparation.  Note that
   2922 		 * this lazy locking also has the effect of lazily forcing
   2923 		 * cache coherency; without the lock acquisition, there's no
   2924 		 * guarantee that modification of arenas[ind] by another thread
   2925 		 * would be seen on this CPU for an arbitrary amount of time.
   2926 		 *
   2927 		 * In general, this approach to modifying a synchronized value
   2928 		 * isn't a good idea, but in this case we only ever modify the
   2929 		 * value once, so things work out well.
   2930 		 */
   2931 		ret = arenas[ind];
   2932 		if (ret == NULL) {
   2933 			/*
   2934 			 * Avoid races with another thread that may have already
   2935 			 * initialized arenas[ind].
   2936 			 */
   2937 			malloc_spin_lock(&arenas_lock);
   2938 			if (arenas[ind] == NULL)
   2939 				ret = arenas_extend((unsigned)ind);
   2940 			else
   2941 				ret = arenas[ind];
   2942 			malloc_spin_unlock(&arenas_lock);
   2943 		}
   2944 	} else
   2945 		ret = arenas[0];
   2946 #endif
   2947 
   2948 	assert(ret != NULL);
   2949 	return (ret);
   2950 }
   2951 
   2952 #ifndef NO_TLS
   2953 /*
   2954  * Choose an arena based on a per-thread value (slow-path code only, called
   2955  * only by choose_arena()).
   2956  */
   2957 static arena_t *
   2958 choose_arena_hard(void)
   2959 {
   2960 	arena_t *ret;
   2961 
   2962 	assert(__isthreaded);
   2963 
   2964 #ifdef MALLOC_BALANCE
   2965 	/* Seed the PRNG used for arena load balancing. */
   2966 	SPRN(balance, (uint32_t)(uintptr_t)(_pthread_self()));
   2967 #endif
   2968 
   2969 	if (narenas > 1) {
   2970 #ifdef MALLOC_BALANCE
   2971 		unsigned ind;
   2972 
   2973 		ind = PRN(balance, narenas_2pow);
   2974 		if ((ret = arenas[ind]) == NULL) {
   2975 			malloc_spin_lock(&arenas_lock);
   2976 			if ((ret = arenas[ind]) == NULL)
   2977 				ret = arenas_extend(ind);
   2978 			malloc_spin_unlock(&arenas_lock);
   2979 		}
   2980 #else
   2981 		malloc_spin_lock(&arenas_lock);
   2982 		if ((ret = arenas[next_arena]) == NULL)
   2983 			ret = arenas_extend(next_arena);
   2984 		next_arena = (next_arena + 1) % narenas;
   2985 		malloc_spin_unlock(&arenas_lock);
   2986 #endif
   2987 	} else
   2988 		ret = arenas[0];
   2989 
   2990 #ifdef MOZ_MEMORY_WINDOWS
   2991 	TlsSetValue(tlsIndex, ret);
   2992 #else
   2993 	arenas_map = ret;
   2994 #endif
   2995 
   2996 	return (ret);
   2997 }
   2998 #endif
   2999 
   3000 static inline int
   3001 arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b)
   3002 {
   3003 	uintptr_t a_chunk = (uintptr_t)a;
   3004 	uintptr_t b_chunk = (uintptr_t)b;
   3005 
   3006 	assert(a != NULL);
   3007 	assert(b != NULL);
   3008 
   3009 	return ((a_chunk > b_chunk) - (a_chunk < b_chunk));
   3010 }
   3011 
   3012 /* Wrap red-black tree macros in functions. */
   3013 rb_wrap(static, arena_chunk_tree_dirty_, arena_chunk_tree_t,
   3014     arena_chunk_t, link_dirty, arena_chunk_comp)
   3015 
   3016 static inline int
   3017 arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
   3018 {
   3019 	uintptr_t a_mapelm = (uintptr_t)a;
   3020 	uintptr_t b_mapelm = (uintptr_t)b;
   3021 
   3022 	assert(a != NULL);
   3023 	assert(b != NULL);
   3024 
   3025 	return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
   3026 }
   3027 
   3028 /* Wrap red-black tree macros in functions. */
   3029 rb_wrap(static, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, link,
   3030     arena_run_comp)
   3031 
   3032 static inline int
   3033 arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
   3034 {
   3035 	int ret;
   3036 	size_t a_size = a->bits & ~pagesize_mask;
   3037 	size_t b_size = b->bits & ~pagesize_mask;
   3038 
   3039 	ret = (a_size > b_size) - (a_size < b_size);
   3040 	if (ret == 0) {
   3041 		uintptr_t a_mapelm, b_mapelm;
   3042 
   3043 		if ((a->bits & CHUNK_MAP_KEY) == 0)
   3044 			a_mapelm = (uintptr_t)a;
   3045 		else {
   3046 			/*
   3047 			 * Treat keys as though they are lower than anything
   3048 			 * else.
   3049 			 */
   3050 			a_mapelm = 0;
   3051 		}
   3052 		b_mapelm = (uintptr_t)b;
   3053 
   3054 		ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
   3055 	}
   3056 
   3057 	return (ret);
   3058 }
   3059 
   3060 /* Wrap red-black tree macros in functions. */
   3061 rb_wrap(static, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, link,
   3062     arena_avail_comp)
   3063 
   3064 static inline void *
   3065 arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin)
   3066 {
   3067 	void *ret;
   3068 	unsigned i, mask, bit, regind;
   3069 
   3070 	assert(run->magic == ARENA_RUN_MAGIC);
   3071 	assert(run->regs_minelm < bin->regs_mask_nelms);
   3072 
   3073 	/*
   3074 	 * Move the first check outside the loop, so that run->regs_minelm can
   3075 	 * be updated unconditionally, without the possibility of updating it
   3076 	 * multiple times.
   3077 	 */
   3078 	i = run->regs_minelm;
   3079 	mask = run->regs_mask[i];
   3080 	if (mask != 0) {
   3081 		/* Usable allocation found. */
   3082 		bit = ffs((int)mask) - 1;
   3083 
   3084 		regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
   3085 		assert(regind < bin->nregs);
   3086 		ret = (void *)(((uintptr_t)run) + bin->reg0_offset
   3087 		    + (bin->reg_size * regind));
   3088 
   3089 		/* Clear bit. */
   3090 		mask ^= (1U << bit);
   3091 		run->regs_mask[i] = mask;
   3092 
   3093 		return (ret);
   3094 	}
   3095 
   3096 	for (i++; i < bin->regs_mask_nelms; i++) {
   3097 		mask = run->regs_mask[i];
   3098 		if (mask != 0) {
   3099 			/* Usable allocation found. */
   3100 			bit = ffs((int)mask) - 1;
   3101 
   3102 			regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
   3103 			assert(regind < bin->nregs);
   3104 			ret = (void *)(((uintptr_t)run) + bin->reg0_offset
   3105 			    + (bin->reg_size * regind));
   3106 
   3107 			/* Clear bit. */
   3108 			mask ^= (1U << bit);
   3109 			run->regs_mask[i] = mask;
   3110 
   3111 			/*
   3112 			 * Make a note that nothing before this element
   3113 			 * contains a free region.
   3114 			 */
   3115 			run->regs_minelm = i; /* Low payoff: + (mask == 0); */
   3116 
   3117 			return (ret);
   3118 		}
   3119 	}
   3120 	/* Not reached. */
   3121 	assert(0);
   3122 	return (NULL);
   3123 }
   3124 
   3125 static inline void
   3126 arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size)
   3127 {
   3128 	/*
   3129 	 * To divide by a number D that is not a power of two we multiply
   3130 	 * by (2^21 / D) and then right shift by 21 positions.
   3131 	 *
   3132 	 *   X / D
   3133 	 *
   3134 	 * becomes
   3135 	 *
   3136 	 *   (X * size_invs[(D >> QUANTUM_2POW_MIN) - 3]) >> SIZE_INV_SHIFT
   3137 	 */
   3138 #define	SIZE_INV_SHIFT 21
   3139 #define	SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s << QUANTUM_2POW_MIN)) + 1)
   3140 	static const unsigned size_invs[] = {
   3141 	    SIZE_INV(3),
   3142 	    SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
   3143 	    SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
   3144 	    SIZE_INV(12),SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
   3145 	    SIZE_INV(16),SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
   3146 	    SIZE_INV(20),SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
   3147 	    SIZE_INV(24),SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
   3148 	    SIZE_INV(28),SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
   3149 #if (QUANTUM_2POW_MIN < 4)
   3150 	    ,
   3151 	    SIZE_INV(32), SIZE_INV(33), SIZE_INV(34), SIZE_INV(35),
   3152 	    SIZE_INV(36), SIZE_INV(37), SIZE_INV(38), SIZE_INV(39),
   3153 	    SIZE_INV(40), SIZE_INV(41), SIZE_INV(42), SIZE_INV(43),
   3154 	    SIZE_INV(44), SIZE_INV(45), SIZE_INV(46), SIZE_INV(47),
   3155 	    SIZE_INV(48), SIZE_INV(49), SIZE_INV(50), SIZE_INV(51),
   3156 	    SIZE_INV(52), SIZE_INV(53), SIZE_INV(54), SIZE_INV(55),
   3157 	    SIZE_INV(56), SIZE_INV(57), SIZE_INV(58), SIZE_INV(59),
   3158 	    SIZE_INV(60), SIZE_INV(61), SIZE_INV(62), SIZE_INV(63)
   3159 #endif
   3160 	};
   3161 	unsigned diff, regind, elm, bit;
   3162 
   3163 	assert(run->magic == ARENA_RUN_MAGIC);
   3164 	assert(((sizeof(size_invs)) / sizeof(unsigned)) + 3
   3165 	    >= (SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN));
   3166 
   3167 	/*
   3168 	 * Avoid doing division with a variable divisor if possible.  Using
   3169 	 * actual division here can reduce allocator throughput by over 20%!
   3170 	 */
   3171 	diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset);
   3172 	if ((size & (size - 1)) == 0) {
   3173 		/*
   3174 		 * log2_table allows fast division of a power of two in the
   3175 		 * [1..128] range.
   3176 		 *
   3177 		 * (x / divisor) becomes (x >> log2_table[divisor - 1]).
   3178 		 */
   3179 		static const unsigned char log2_table[] = {
   3180 		    0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
   3181 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
   3182 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   3183 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
   3184 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   3185 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   3186 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   3187 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7
   3188 		};
   3189 
   3190 		if (size <= 128)
   3191 			regind = (diff >> log2_table[size - 1]);
   3192 		else if (size <= 32768)
   3193 			regind = diff >> (8 + log2_table[(size >> 8) - 1]);
   3194 		else {
   3195 			/*
   3196 			 * The run size is too large for us to use the lookup
   3197 			 * table.  Use real division.
   3198 			 */
   3199 			regind = diff / size;
   3200 		}
   3201 	} else if (size <= ((sizeof(size_invs) / sizeof(unsigned))
   3202 	    << QUANTUM_2POW_MIN) + 2) {
   3203 		regind = size_invs[(size >> QUANTUM_2POW_MIN) - 3] * diff;
   3204 		regind >>= SIZE_INV_SHIFT;
   3205 	} else {
   3206 		/*
   3207 		 * size_invs isn't large enough to handle this size class, so
   3208 		 * calculate regind using actual division.  This only happens
   3209 		 * if the user increases small_max via the 'S' runtime
   3210 		 * configuration option.
   3211 		 */
   3212 		regind = diff / size;
   3213 	};
   3214 	assert(diff == regind * size);
   3215 	assert(regind < bin->nregs);
   3216 
   3217 	elm = regind >> (SIZEOF_INT_2POW + 3);
   3218 	if (elm < run->regs_minelm)
   3219 		run->regs_minelm = elm;
   3220 	bit = regind - (elm << (SIZEOF_INT_2POW + 3));
   3221 	assert((run->regs_mask[elm] & (1U << bit)) == 0);
   3222 	run->regs_mask[elm] |= (1U << bit);
   3223 #undef SIZE_INV
   3224 #undef SIZE_INV_SHIFT
   3225 }
   3226 
   3227 static void
   3228 arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
   3229     bool zero)
   3230 {
   3231 	arena_chunk_t *chunk;
   3232 	size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i;
   3233 
   3234 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
   3235 	old_ndirty = chunk->ndirty;
   3236 	run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk)
   3237 	    >> pagesize_2pow);
   3238 	total_pages = (chunk->map[run_ind].bits & ~pagesize_mask) >>
   3239 	    pagesize_2pow;
   3240 	need_pages = (size >> pagesize_2pow);
   3241 	assert(need_pages > 0);
   3242 	assert(need_pages <= total_pages);
   3243 	rem_pages = total_pages - need_pages;
   3244 
   3245 	arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]);
   3246 
   3247 	/* Keep track of trailing unused pages for later use. */
   3248 	if (rem_pages > 0) {
   3249 		chunk->map[run_ind+need_pages].bits = (rem_pages <<
   3250 		    pagesize_2pow) | (chunk->map[run_ind+need_pages].bits &
   3251 		    pagesize_mask);
   3252 		chunk->map[run_ind+total_pages-1].bits = (rem_pages <<
   3253 		    pagesize_2pow) | (chunk->map[run_ind+total_pages-1].bits &
   3254 		    pagesize_mask);
   3255 		arena_avail_tree_insert(&arena->runs_avail,
   3256 		    &chunk->map[run_ind+need_pages]);
   3257 	}
   3258 
   3259 	for (i = 0; i < need_pages; i++) {
   3260 #ifdef MALLOC_DECOMMIT
   3261 		/*
   3262 		 * Commit decommitted pages if necessary.  If a decommitted
   3263 		 * page is encountered, commit all needed adjacent decommitted
   3264 		 * pages in one operation, in order to reduce system call
   3265 		 * overhead.
   3266 		 */
   3267 		if (chunk->map[run_ind + i].bits & CHUNK_MAP_DECOMMITTED) {
   3268 			size_t j;
   3269 
   3270 			/*
   3271 			 * Advance i+j to just past the index of the last page
   3272 			 * to commit.  Clear CHUNK_MAP_DECOMMITTED along the
   3273 			 * way.
   3274 			 */
   3275 			for (j = 0; i + j < need_pages && (chunk->map[run_ind +
   3276 			    i + j].bits & CHUNK_MAP_DECOMMITTED); j++) {
   3277 				chunk->map[run_ind + i + j].bits ^=
   3278 				    CHUNK_MAP_DECOMMITTED;
   3279 			}
   3280 
   3281 			pages_commit((void *)((uintptr_t)chunk + ((run_ind + i)
   3282 			    << pagesize_2pow)), (j << pagesize_2pow));
   3283 #  ifdef MALLOC_STATS
   3284 			arena->stats.ncommit++;
   3285 #  endif
   3286 		} else /* No need to zero since commit zeros. */
   3287 #endif
   3288 
   3289 		/* Zero if necessary. */
   3290 		if (zero) {
   3291 			if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED)
   3292 			    == 0) {
   3293 				VALGRIND_MALLOCLIKE_BLOCK((void *)((uintptr_t)
   3294 				    chunk + ((run_ind + i) << pagesize_2pow)),
   3295 				    pagesize, 0, false);
   3296 				memset((void *)((uintptr_t)chunk + ((run_ind
   3297 				    + i) << pagesize_2pow)), 0, pagesize);
   3298 				VALGRIND_FREELIKE_BLOCK((void *)((uintptr_t)
   3299 				    chunk + ((run_ind + i) << pagesize_2pow)),
   3300 				    0);
   3301 				/* CHUNK_MAP_ZEROED is cleared below. */
   3302 			}
   3303 		}
   3304 
   3305 		/* Update dirty page accounting. */
   3306 		if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) {
   3307 			chunk->ndirty--;
   3308 			arena->ndirty--;
   3309 			/* CHUNK_MAP_DIRTY is cleared below. */
   3310 		}
   3311 
   3312 		/* Initialize the chunk map. */
   3313 		if (large) {
   3314 			chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE
   3315 			    | CHUNK_MAP_ALLOCATED;
   3316 		} else {
   3317 			chunk->map[run_ind + i].bits = (size_t)run
   3318 			    | CHUNK_MAP_ALLOCATED;
   3319 		}
   3320 	}
   3321 
   3322 	/*
   3323 	 * Set the run size only in the first element for large runs.  This is
   3324 	 * primarily a debugging aid, since the lack of size info for trailing
   3325 	 * pages only matters if the application tries to operate on an
   3326 	 * interior pointer.
   3327 	 */
   3328 	if (large)
   3329 		chunk->map[run_ind].bits |= size;
   3330 
   3331 	if (chunk->ndirty == 0 && old_ndirty > 0)
   3332 		arena_chunk_tree_dirty_remove(&arena->chunks_dirty, chunk);
   3333 }
   3334 
   3335 static void
   3336 arena_chunk_init(arena_t *arena, arena_chunk_t *chunk)
   3337 {
   3338 	arena_run_t *run;
   3339 	size_t i;
   3340 
   3341 	VALGRIND_MALLOCLIKE_BLOCK(chunk, (arena_chunk_header_npages <<
   3342 	    pagesize_2pow), 0, false);
   3343 #ifdef MALLOC_STATS
   3344 	arena->stats.mapped += chunksize;
   3345 #endif
   3346 
   3347 	chunk->arena = arena;
   3348 
   3349 	/*
   3350 	 * Claim that no pages are in use, since the header is merely overhead.
   3351 	 */
   3352 	chunk->ndirty = 0;
   3353 
   3354 	/* Initialize the map to contain one maximal free untouched run. */
   3355 	run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages <<
   3356 	    pagesize_2pow));
   3357 	for (i = 0; i < arena_chunk_header_npages; i++)
   3358 		chunk->map[i].bits = 0;
   3359 	chunk->map[i].bits = arena_maxclass
   3360 #ifdef MALLOC_DECOMMIT
   3361 	    | CHUNK_MAP_DECOMMITTED
   3362 #endif
   3363 	    | CHUNK_MAP_ZEROED;
   3364 	for (i++; i < chunk_npages-1; i++) {
   3365 		chunk->map[i].bits =
   3366 #ifdef MALLOC_DECOMMIT
   3367 		    CHUNK_MAP_DECOMMITTED |
   3368 #endif
   3369 		    CHUNK_MAP_ZEROED;
   3370 	}
   3371 	chunk->map[chunk_npages-1].bits = arena_maxclass
   3372 #ifdef MALLOC_DECOMMIT
   3373 	    | CHUNK_MAP_DECOMMITTED
   3374 #endif
   3375 	    | CHUNK_MAP_ZEROED;
   3376 
   3377 #ifdef MALLOC_DECOMMIT
   3378 	/*
   3379 	 * Start out decommitted, in order to force a closer correspondence
   3380 	 * between dirty pages and committed untouched pages.
   3381 	 */
   3382 	pages_decommit(run, arena_maxclass);
   3383 #  ifdef MALLOC_STATS
   3384 	arena->stats.ndecommit++;
   3385 	arena->stats.decommitted += (chunk_npages - arena_chunk_header_npages);
   3386 #  endif
   3387 #endif
   3388 
   3389 	/* Insert the run into the runs_avail tree. */
   3390 	arena_avail_tree_insert(&arena->runs_avail,
   3391 	    &chunk->map[arena_chunk_header_npages]);
   3392 }
   3393 
   3394 static void
   3395 arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
   3396 {
   3397 
   3398 	if (arena->spare != NULL) {
   3399 		if (arena->spare->ndirty > 0) {
   3400 			arena_chunk_tree_dirty_remove(
   3401 			    &chunk->arena->chunks_dirty, arena->spare);
   3402 			arena->ndirty -= arena->spare->ndirty;
   3403 		}
   3404 		VALGRIND_FREELIKE_BLOCK(arena->spare, 0);
   3405 		chunk_dealloc((void *)arena->spare, chunksize);
   3406 #ifdef MALLOC_STATS
   3407 		arena->stats.mapped -= chunksize;
   3408 #endif
   3409 	}
   3410 
   3411 	/*
   3412 	 * Remove run from runs_avail, regardless of whether this chunk
   3413 	 * will be cached, so that the arena does not use it.  Dirty page
   3414 	 * flushing only uses the chunks_dirty tree, so leaving this chunk in
   3415 	 * the chunks_* trees is sufficient for that purpose.
   3416 	 */
   3417 	arena_avail_tree_remove(&arena->runs_avail,
   3418 	    &chunk->map[arena_chunk_header_npages]);
   3419 
   3420 	arena->spare = chunk;
   3421 }
   3422 
   3423 static arena_run_t *
   3424 arena_run_alloc(arena_t *arena, arena_bin_t *bin, size_t size, bool large,
   3425     bool zero)
   3426 {
   3427 	arena_chunk_t *chunk;
   3428 	arena_run_t *run;
   3429 	arena_chunk_map_t *mapelm, key;
   3430 
   3431 	assert(size <= arena_maxclass);
   3432 	assert((size & pagesize_mask) == 0);
   3433 
   3434 	chunk = NULL;
   3435 	while (true) {
   3436 		/* Search the arena's chunks for the lowest best fit. */
   3437 		key.bits = size | CHUNK_MAP_KEY;
   3438 		mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);
   3439 		if (mapelm != NULL) {
   3440 			arena_chunk_t *run_chunk = (arena_chunk_t*)CHUNK_ADDR2BASE(mapelm);
   3441 			size_t pageind = ((uintptr_t)mapelm -
   3442 			    (uintptr_t)run_chunk->map) /
   3443 			    sizeof(arena_chunk_map_t);
   3444 
   3445 			if (chunk != NULL)
   3446 				chunk_dealloc(chunk, chunksize);
   3447 			run = (arena_run_t *)((uintptr_t)run_chunk + (pageind
   3448 			    << pagesize_2pow));
   3449 			arena_run_split(arena, run, size, large, zero);
   3450 			return (run);
   3451 		}
   3452 
   3453 		if (arena->spare != NULL) {
   3454 			/* Use the spare. */
   3455 			chunk = arena->spare;
   3456 			arena->spare = NULL;
   3457 			run = (arena_run_t *)((uintptr_t)chunk +
   3458 			    (arena_chunk_header_npages << pagesize_2pow));
   3459 			/* Insert the run into the runs_avail tree. */
   3460 			arena_avail_tree_insert(&arena->runs_avail,
   3461 			    &chunk->map[arena_chunk_header_npages]);
   3462 			arena_run_split(arena, run, size, large, zero);
   3463 			return (run);
   3464 		}
   3465 
   3466 		/*
   3467 		 * No usable runs.  Create a new chunk from which to allocate
   3468 		 * the run.
   3469 		 */
   3470 		if (chunk == NULL) {
   3471 			uint64_t chunk_seq;
   3472 
   3473 			/*
   3474 			 * Record the chunk allocation sequence number in order
   3475 			 * to detect races.
   3476 			 */
   3477 			arena->chunk_seq++;
   3478 			chunk_seq = arena->chunk_seq;
   3479 
   3480 			/*
   3481 			 * Drop the arena lock while allocating a chunk, since
   3482 			 * reserve notifications may cause recursive
   3483 			 * allocation.  Dropping the lock here opens an
   3484 			 * allocataion race, but we recover.
   3485 			 */
   3486 			malloc_mutex_unlock(&arena->lock);
   3487 			chunk = (arena_chunk_t *)chunk_alloc(chunksize, true,
   3488 			    true);
   3489 			malloc_mutex_lock(&arena->lock);
   3490 
   3491 			/*
   3492 			 * Check whether a race allowed a usable run to appear.
   3493 			 */
   3494 			if (bin != NULL && (run = bin->runcur) != NULL &&
   3495 			    run->nfree > 0) {
   3496 				if (chunk != NULL)
   3497 					chunk_dealloc(chunk, chunksize);
   3498 				return (run);
   3499 			}
   3500 
   3501 			/*
   3502 			 * If this thread raced with another such that multiple
   3503 			 * chunks were allocated, make sure that there is still
   3504 			 * inadequate space before using this chunk.
   3505 			 */
   3506 			if (chunk_seq != arena->chunk_seq)
   3507 				continue;
   3508 
   3509 			/*
   3510 			 * Check for an error *after* checking for a race,
   3511 			 * since a race could also cause a transient OOM
   3512 			 * condition.
   3513 			 */
   3514 			if (chunk == NULL)
   3515 				return (NULL);
   3516 		}
   3517 
   3518 		arena_chunk_init(arena, chunk);
   3519 		run = (arena_run_t *)((uintptr_t)chunk +
   3520 		    (arena_chunk_header_npages << pagesize_2pow));
   3521 		/* Update page map. */
   3522 		arena_run_split(arena, run, size, large, zero);
   3523 		return (run);
   3524 	}
   3525 }
   3526 
   3527 static void
   3528 arena_purge(arena_t *arena)
   3529 {
   3530 	arena_chunk_t *chunk;
   3531 	size_t i, npages;
   3532 #ifdef MALLOC_DEBUG
   3533 	size_t ndirty = 0;
   3534 	rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty,
   3535 	    chunk) {
   3536 		ndirty += chunk->ndirty;
   3537 	} rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk)
   3538 	assert(ndirty == arena->ndirty);
   3539 #endif
   3540 	assert(arena->ndirty > opt_dirty_max);
   3541 
   3542 #ifdef MALLOC_STATS
   3543 	arena->stats.npurge++;
   3544 #endif
   3545 
   3546 	/*
   3547 	 * Iterate downward through chunks until enough dirty memory has been
   3548 	 * purged.  Terminate as soon as possible in order to minimize the
   3549 	 * number of system calls, even if a chunk has only been partially
   3550 	 * purged.
   3551 	 */
   3552 	while (arena->ndirty > (opt_dirty_max >> 1)) {
   3553 		chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
   3554 		assert(chunk != NULL);
   3555 
   3556 		for (i = chunk_npages - 1; chunk->ndirty > 0; i--) {
   3557 			assert(i >= arena_chunk_header_npages);
   3558 
   3559 			if (chunk->map[i].bits & CHUNK_MAP_DIRTY) {
   3560 #ifdef MALLOC_DECOMMIT
   3561 				assert((chunk->map[i].bits &
   3562 				    CHUNK_MAP_DECOMMITTED) == 0);
   3563 #endif
   3564 				chunk->map[i].bits ^=
   3565 #ifdef MALLOC_DECOMMIT
   3566 				    CHUNK_MAP_DECOMMITTED |
   3567 #endif
   3568 				    CHUNK_MAP_DIRTY;
   3569 				/* Find adjacent dirty run(s). */
   3570 				for (npages = 1; i > arena_chunk_header_npages
   3571 				    && (chunk->map[i - 1].bits &
   3572 				    CHUNK_MAP_DIRTY); npages++) {
   3573 					i--;
   3574 #ifdef MALLOC_DECOMMIT
   3575 					assert((chunk->map[i].bits &
   3576 					    CHUNK_MAP_DECOMMITTED) == 0);
   3577 #endif
   3578 					chunk->map[i].bits ^=
   3579 #ifdef MALLOC_DECOMMIT
   3580 					    CHUNK_MAP_DECOMMITTED |
   3581 #endif
   3582 					    CHUNK_MAP_DIRTY;
   3583 				}
   3584 				chunk->ndirty -= npages;
   3585 				arena->ndirty -= npages;
   3586 
   3587 #ifdef MALLOC_DECOMMIT
   3588 				pages_decommit((void *)((uintptr_t)
   3589 				    chunk + (i << pagesize_2pow)),
   3590 				    (npages << pagesize_2pow));
   3591 #  ifdef MALLOC_STATS
   3592 				arena->stats.ndecommit++;
   3593 				arena->stats.decommitted += npages;
   3594 #  endif
   3595 #else
   3596 				madvise((void *)((uintptr_t)chunk + (i <<
   3597 				    pagesize_2pow)), (npages << pagesize_2pow),
   3598 				    MADV_FREE);
   3599 #endif
   3600 #ifdef MALLOC_STATS
   3601 				arena->stats.nmadvise++;
   3602 				arena->stats.purged += npages;
   3603 #endif
   3604 				if (arena->ndirty <= (opt_dirty_max >> 1))
   3605 					break;
   3606 			}
   3607 		}
   3608 
   3609 		if (chunk->ndirty == 0) {
   3610 			arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
   3611 			    chunk);
   3612 		}
   3613 	}
   3614 }
   3615 
   3616 static void
   3617 arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
   3618 {
   3619 	arena_chunk_t *chunk;
   3620 	size_t size, run_ind, run_pages;
   3621 
   3622 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
   3623 	run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk)
   3624 	    >> pagesize_2pow);
   3625 	assert(run_ind >= arena_chunk_header_npages);
   3626 	assert(run_ind < chunk_npages);
   3627 	if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0)
   3628 		size = chunk->map[run_ind].bits & ~pagesize_mask;
   3629 	else
   3630 		size = run->bin->run_size;
   3631 	run_pages = (size >> pagesize_2pow);
   3632 
   3633 	/* Mark pages as unallocated in the chunk map. */
   3634 	if (dirty) {
   3635 		size_t i;
   3636 
   3637 		for (i = 0; i < run_pages; i++) {
   3638 			assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY)
   3639 			    == 0);
   3640 			chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY;
   3641 		}
   3642 
   3643 		if (chunk->ndirty == 0) {
   3644 			arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
   3645 			    chunk);
   3646 		}
   3647 		chunk->ndirty += run_pages;
   3648 		arena->ndirty += run_pages;
   3649 	} else {
   3650 		size_t i;
   3651 
   3652 		for (i = 0; i < run_pages; i++) {
   3653 			chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE |
   3654 			    CHUNK_MAP_ALLOCATED);
   3655 		}
   3656 	}
   3657 	chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
   3658 	    pagesize_mask);
   3659 	chunk->map[run_ind+run_pages-1].bits = size |
   3660 	    (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
   3661 
   3662 	/* Try to coalesce forward. */
   3663 	if (run_ind + run_pages < chunk_npages &&
   3664 	    (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) {
   3665 		size_t nrun_size = chunk->map[run_ind+run_pages].bits &
   3666 		    ~pagesize_mask;
   3667 
   3668 		/*
   3669 		 * Remove successor from runs_avail; the coalesced run is
   3670 		 * inserted later.
   3671 		 */
   3672 		arena_avail_tree_remove(&arena->runs_avail,
   3673 		    &chunk->map[run_ind+run_pages]);
   3674 
   3675 		size += nrun_size;
   3676 		run_pages = size >> pagesize_2pow;
   3677 
   3678 		assert((chunk->map[run_ind+run_pages-1].bits & ~pagesize_mask)
   3679 		    == nrun_size);
   3680 		chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
   3681 		    pagesize_mask);
   3682 		chunk->map[run_ind+run_pages-1].bits = size |
   3683 		    (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
   3684 	}
   3685 
   3686 	/* Try to coalesce backward. */
   3687 	if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits &
   3688 	    CHUNK_MAP_ALLOCATED) == 0) {
   3689 		size_t prun_size = chunk->map[run_ind-1].bits & ~pagesize_mask;
   3690 
   3691 		run_ind -= prun_size >> pagesize_2pow;
   3692 
   3693 		/*
   3694 		 * Remove predecessor from runs_avail; the coalesced run is
   3695 		 * inserted later.
   3696 		 */
   3697 		arena_avail_tree_remove(&arena->runs_avail,
   3698 		    &chunk->map[run_ind]);
   3699 
   3700 		size += prun_size;
   3701 		run_pages = size >> pagesize_2pow;
   3702 
   3703 		assert((chunk->map[run_ind].bits & ~pagesize_mask) ==
   3704 		    prun_size);
   3705 		chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
   3706 		    pagesize_mask);
   3707 		chunk->map[run_ind+run_pages-1].bits = size |
   3708 		    (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
   3709 	}
   3710 
   3711 	/* Insert into runs_avail, now that coalescing is complete. */
   3712 	arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]);
   3713 
   3714 	/* Deallocate chunk if it is now completely unused. */
   3715 	if ((chunk->map[arena_chunk_header_npages].bits & (~pagesize_mask |
   3716 	    CHUNK_MAP_ALLOCATED)) == arena_maxclass)
   3717 		arena_chunk_dealloc(arena, chunk);
   3718 
   3719 	/* Enforce opt_dirty_max. */
   3720 	if (arena->ndirty > opt_dirty_max)
   3721 		arena_purge(arena);
   3722 }
   3723 
   3724 static void
   3725 arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
   3726     size_t oldsize, size_t newsize)
   3727 {
   3728 	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
   3729 	size_t head_npages = (oldsize - newsize) >> pagesize_2pow;
   3730 
   3731 	assert(oldsize > newsize);
   3732 
   3733 	/*
   3734 	 * Update the chunk map so that arena_run_dalloc() can treat the
   3735 	 * leading run as separately allocated.
   3736 	 */
   3737 	chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE |
   3738 	    CHUNK_MAP_ALLOCATED;
   3739 	chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE |
   3740 	    CHUNK_MAP_ALLOCATED;
   3741 
   3742 	arena_run_dalloc(arena, run, false);
   3743 }
   3744 
   3745 static void
   3746 arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
   3747     size_t oldsize, size_t newsize, bool dirty)
   3748 {
   3749 	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
   3750 	size_t npages = newsize >> pagesize_2pow;
   3751 
   3752 	assert(oldsize > newsize);
   3753 
   3754 	/*
   3755 	 * Update the chunk map so that arena_run_dalloc() can treat the
   3756 	 * trailing run as separately allocated.
   3757 	 */
   3758 	chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE |
   3759 	    CHUNK_MAP_ALLOCATED;
   3760 	chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE
   3761 	    | CHUNK_MAP_ALLOCATED;
   3762 
   3763 	arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
   3764 	    dirty);
   3765 }
   3766 
   3767 static arena_run_t *
   3768 arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
   3769 {
   3770 	arena_chunk_map_t *mapelm;
   3771 	arena_run_t *run;
   3772 	unsigned i, remainder;
   3773 
   3774 	/* Look for a usable run. */
   3775 	mapelm = arena_run_tree_first(&bin->runs);
   3776 	if (mapelm != NULL) {
   3777 		/* run is guaranteed to have available space. */
   3778 		arena_run_tree_remove(&bin->runs, mapelm);
   3779 		run = (arena_run_t *)(mapelm->bits & ~pagesize_mask);
   3780 #ifdef MALLOC_STATS
   3781 		bin->stats.reruns++;
   3782 #endif
   3783 		return (run);
   3784 	}
   3785 	/* No existing runs have any space available. */
   3786 
   3787 	/* Allocate a new run. */
   3788 	run = arena_run_alloc(arena, bin, bin->run_size, false, false);
   3789 	if (run == NULL)
   3790 		return (NULL);
   3791 	/*
   3792 	 * Don't initialize if a race in arena_run_alloc() allowed an existing
   3793 	 * run to become usable.
   3794 	 */
   3795 	if (run == bin->runcur)
   3796 		return (run);
   3797 
   3798 	VALGRIND_MALLOCLIKE_BLOCK(run, sizeof(arena_run_t) + (sizeof(unsigned) *
   3799 	    (bin->regs_mask_nelms - 1)), 0, false);
   3800 
   3801 	/* Initialize run internals. */
   3802 	run->bin = bin;
   3803 
   3804 	for (i = 0; i < bin->regs_mask_nelms - 1; i++)
   3805 		run->regs_mask[i] = UINT_MAX;
   3806 	remainder = bin->nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1);
   3807 	if (remainder == 0)
   3808 		run->regs_mask[i] = UINT_MAX;
   3809 	else {
   3810 		/* The last element has spare bits that need to be unset. */
   3811 		run->regs_mask[i] = (UINT_MAX >> ((1U << (SIZEOF_INT_2POW + 3))
   3812 		    - remainder));
   3813 	}
   3814 
   3815 	run->regs_minelm = 0;
   3816 
   3817 	run->nfree = bin->nregs;
   3818 #ifdef MALLOC_DEBUG
   3819 	run->magic = ARENA_RUN_MAGIC;
   3820 #endif
   3821 
   3822 #ifdef MALLOC_STATS
   3823 	bin->stats.nruns++;
   3824 	bin->stats.curruns++;
   3825 	if (bin->stats.curruns > bin->stats.highruns)
   3826 		bin->stats.highruns = bin->stats.curruns;
   3827 #endif
   3828 	return (run);
   3829 }
   3830 
   3831 /* bin->runcur must have space available before this function is called. */
   3832 static inline void *
   3833 arena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run)
   3834 {
   3835 	void *ret;
   3836 
   3837 	assert(run->magic == ARENA_RUN_MAGIC);
   3838 	assert(run->nfree > 0);
   3839 
   3840 	ret = arena_run_reg_alloc(run, bin);
   3841 	assert(ret != NULL);
   3842 	run->nfree--;
   3843 
   3844 	return (ret);
   3845 }
   3846 
   3847 /* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */
   3848 static void *
   3849 arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
   3850 {
   3851 
   3852 	bin->runcur = arena_bin_nonfull_run_get(arena, bin);
   3853 	if (bin->runcur == NULL)
   3854 		return (NULL);
   3855 	assert(bin->runcur->magic == ARENA_RUN_MAGIC);
   3856 	assert(bin->runcur->nfree > 0);
   3857 
   3858 	return (arena_bin_malloc_easy(arena, bin, bin->runcur));
   3859 }
   3860 
   3861 /*
   3862  * Calculate bin->run_size such that it meets the following constraints:
   3863  *
   3864  *   *) bin->run_size >= min_run_size
   3865  *   *) bin->run_size <= arena_maxclass
   3866  *   *) bin->run_size <= RUN_MAX_SMALL
   3867  *   *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
   3868  *
   3869  * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are
   3870  * also calculated here, since these settings are all interdependent.
   3871  */
   3872 static size_t
   3873 arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
   3874 {
   3875 	size_t try_run_size, good_run_size;
   3876 	unsigned good_nregs, good_mask_nelms, good_reg0_offset;
   3877 	unsigned try_nregs, try_mask_nelms, try_reg0_offset;
   3878 
   3879 	assert(min_run_size >= pagesize);
   3880 	assert(min_run_size <= arena_maxclass);
   3881 	assert(min_run_size <= RUN_MAX_SMALL);
   3882 
   3883 	/*
   3884 	 * Calculate known-valid settings before entering the run_size
   3885 	 * expansion loop, so that the first part of the loop always copies
   3886 	 * valid settings.
   3887 	 *
   3888 	 * The do..while loop iteratively reduces the number of regions until
   3889 	 * the run header and the regions no longer overlap.  A closed formula
   3890 	 * would be quite messy, since there is an interdependency between the
   3891 	 * header's mask length and the number of regions.
   3892 	 */
   3893 	try_run_size = min_run_size;
   3894 	try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size)
   3895 	    + 1; /* Counter-act try_nregs-- in loop. */
   3896 	do {
   3897 		try_nregs--;
   3898 		try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
   3899 		    ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ? 1 : 0);
   3900 		try_reg0_offset = try_run_size - (try_nregs * bin->reg_size);
   3901 	} while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1))
   3902 	    > try_reg0_offset);
   3903 
   3904 	/* run_size expansion loop. */
   3905 	do {
   3906 		/*
   3907 		 * Copy valid settings before trying more aggressive settings.
   3908 		 */
   3909 		good_run_size = try_run_size;
   3910 		good_nregs = try_nregs;
   3911 		good_mask_nelms = try_mask_nelms;
   3912 		good_reg0_offset = try_reg0_offset;
   3913 
   3914 		/* Try more aggressive settings. */
   3915 		try_run_size += pagesize;
   3916 		try_nregs = ((try_run_size - sizeof(arena_run_t)) /
   3917 		    bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */
   3918 		do {
   3919 			try_nregs--;
   3920 			try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
   3921 			    ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ?
   3922 			    1 : 0);
   3923 			try_reg0_offset = try_run_size - (try_nregs *
   3924 			    bin->reg_size);
   3925 		} while (sizeof(arena_run_t) + (sizeof(unsigned) *
   3926 		    (try_mask_nelms - 1)) > try_reg0_offset);
   3927 	} while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL
   3928 	    && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
   3929 	    && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
   3930 
   3931 	assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1))
   3932 	    <= good_reg0_offset);
   3933 	assert((good_mask_nelms << (SIZEOF_INT_2POW + 3)) >= good_nregs);
   3934 
   3935 	/* Copy final settings. */
   3936 	bin->run_size = good_run_size;
   3937 	bin->nregs = good_nregs;
   3938 	bin->regs_mask_nelms = good_mask_nelms;
   3939 	bin->reg0_offset = good_reg0_offset;
   3940 
   3941 	return (good_run_size);
   3942 }
   3943 
   3944 #ifdef MALLOC_BALANCE
   3945 static inline void
   3946 arena_lock_balance(arena_t *arena)
   3947 {
   3948 	unsigned contention;
   3949 
   3950 	contention = malloc_spin_lock(&arena->lock);
   3951 	if (narenas > 1) {
   3952 		/*
   3953 		 * Calculate the exponentially averaged contention for this
   3954 		 * arena.  Due to integer math always rounding down, this value
   3955 		 * decays somewhat faster then normal.
   3956 		 */
   3957 		arena->contention = (((uint64_t)arena->contention
   3958 		    * (uint64_t)((1U << BALANCE_ALPHA_INV_2POW)-1))
   3959 		    + (uint64_t)contention) >> BALANCE_ALPHA_INV_2POW;
   3960 		if (arena->contention >= opt_balance_threshold)
   3961 			arena_lock_balance_hard(arena);
   3962 	}
   3963 }
   3964 
   3965 static void
   3966 arena_lock_balance_hard(arena_t *arena)
   3967 {
   3968 	uint32_t ind;
   3969 
   3970 	arena->contention = 0;
   3971 #ifdef MALLOC_STATS
   3972 	arena->stats.nbalance++;
   3973 #endif
   3974 	ind = PRN(balance, narenas_2pow);
   3975 	if (arenas[ind] != NULL) {
   3976 #ifdef MOZ_MEMORY_WINDOWS
   3977 		TlsSetValue(tlsIndex, arenas[ind]);
   3978 #else
   3979 		arenas_map = arenas[ind];
   3980 #endif
   3981 	} else {
   3982 		malloc_spin_lock(&arenas_lock);
   3983 		if (arenas[ind] != NULL) {
   3984 #ifdef MOZ_MEMORY_WINDOWS
   3985 			TlsSetValue(tlsIndex, arenas[ind]);
   3986 #else
   3987 			arenas_map = arenas[ind];
   3988 #endif
   3989 		} else {
   3990 #ifdef MOZ_MEMORY_WINDOWS
   3991 			TlsSetValue(tlsIndex, arenas_extend(ind));
   3992 #else
   3993 			arenas_map = arenas_extend(ind);
   3994 #endif
   3995 		}
   3996 		malloc_spin_unlock(&arenas_lock);
   3997 	}
   3998 }
   3999 #endif
   4000 
   4001 static inline void *
   4002 arena_malloc_small(arena_t *arena, size_t size, bool zero)
   4003 {
   4004 	void *ret;
   4005 	arena_bin_t *bin;
   4006 	arena_run_t *run;
   4007 
   4008 	if (size < small_min) {
   4009 		/* Tiny. */
   4010 		size = pow2_ceil(size);
   4011 		bin = &arena->bins[ffs((int)(size >> (TINY_MIN_2POW +
   4012 		    1)))];
   4013 #if (!defined(NDEBUG) || defined(MALLOC_STATS))
   4014 		/*
   4015 		 * Bin calculation is always correct, but we may need
   4016 		 * to fix size for the purposes of assertions and/or
   4017 		 * stats accuracy.
   4018 		 */
   4019 		if (size < (1U << TINY_MIN_2POW))
   4020 			size = (1U << TINY_MIN_2POW);
   4021 #endif
   4022 	} else if (size <= small_max) {
   4023 		/* Quantum-spaced. */
   4024 		size = QUANTUM_CEILING(size);
   4025 		bin = &arena->bins[ntbins + (size >> opt_quantum_2pow)
   4026 		    - 1];
   4027 	} else {
   4028 		/* Sub-page. */
   4029 		size = pow2_ceil(size);
   4030 		bin = &arena->bins[ntbins + nqbins
   4031 		    + (ffs((int)(size >> opt_small_max_2pow)) - 2)];
   4032 	}
   4033 	assert(size == bin->reg_size);
   4034 
   4035 #ifdef MALLOC_BALANCE
   4036 	arena_lock_balance(arena);
   4037 #else
   4038 	malloc_spin_lock(&arena->lock);
   4039 #endif
   4040 	if ((run = bin->runcur) != NULL && run->nfree > 0)
   4041 		ret = arena_bin_malloc_easy(arena, bin, run);
   4042 	else
   4043 		ret = arena_bin_malloc_hard(arena, bin);
   4044 
   4045 	if (ret == NULL) {
   4046 		malloc_spin_unlock(&arena->lock);
   4047 		return (NULL);
   4048 	}
   4049 
   4050 #ifdef MALLOC_STATS
   4051 	bin->stats.nrequests++;
   4052 	arena->stats.nmalloc_small++;
   4053 	arena->stats.allocated_small += size;
   4054 #endif
   4055 	malloc_spin_unlock(&arena->lock);
   4056 
   4057 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
   4058 	if (zero == false) {
   4059 #ifdef MALLOC_FILL
   4060 		if (opt_junk)
   4061 			memset(ret, 0xa5, size);
   4062 		else if (opt_zero)
   4063 			memset(ret, 0, size);
   4064 #endif
   4065 	} else
   4066 		memset(ret, 0, size);
   4067 
   4068 	return (ret);
   4069 }
   4070 
   4071 static void *
   4072 arena_malloc_large(arena_t *arena, size_t size, bool zero)
   4073 {
   4074 	void *ret;
   4075 
   4076 	/* Large allocation. */
   4077 	size = PAGE_CEILING(size);
   4078 #ifdef MALLOC_BALANCE
   4079 	arena_lock_balance(arena);
   4080 #else
   4081 	malloc_spin_lock(&arena->lock);
   4082 #endif
   4083 	ret = (void *)arena_run_alloc(arena, NULL, size, true, zero);
   4084 	if (ret == NULL) {
   4085 		malloc_spin_unlock(&arena->lock);
   4086 		return (NULL);
   4087 	}
   4088 #ifdef MALLOC_STATS
   4089 	arena->stats.nmalloc_large++;
   4090 	arena->stats.allocated_large += size;
   4091 #endif
   4092 	malloc_spin_unlock(&arena->lock);
   4093 
   4094 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
   4095 	if (zero == false) {
   4096 #ifdef MALLOC_FILL
   4097 		if (opt_junk)
   4098 			memset(ret, 0xa5, size);
   4099 		else if (opt_zero)
   4100 			memset(ret, 0, size);
   4101 #endif
   4102 	}
   4103 
   4104 	return (ret);
   4105 }
   4106 
   4107 static inline void *
   4108 arena_malloc(arena_t *arena, size_t size, bool zero)
   4109 {
   4110 
   4111 	assert(arena != NULL);
   4112 	assert(arena->magic == ARENA_MAGIC);
   4113 	assert(size != 0);
   4114 	assert(QUANTUM_CEILING(size) <= arena_maxclass);
   4115 
   4116 	if (size <= bin_maxclass) {
   4117 		return (arena_malloc_small(arena, size, zero));
   4118 	} else
   4119 		return (arena_malloc_large(arena, size, zero));
   4120 }
   4121 
   4122 static inline void *
   4123 imalloc(size_t size)
   4124 {
   4125 
   4126 	assert(size != 0);
   4127 
   4128 	if (size <= arena_maxclass)
   4129 		return (arena_malloc(choose_arena(), size, false));
   4130 	else
   4131 		return (huge_malloc(size, false));
   4132 }
   4133 
   4134 static inline void *
   4135 icalloc(size_t size)
   4136 {
   4137 
   4138 	if (size <= arena_maxclass)
   4139 		return (arena_malloc(choose_arena(), size, true));
   4140 	else
   4141 		return (huge_malloc(size, true));
   4142 }
   4143 
   4144 /* Only handles large allocations that require more than page alignment. */
   4145 static void *
   4146 arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size)
   4147 {
   4148 	void *ret;
   4149 	size_t offset;
   4150 	arena_chunk_t *chunk;
   4151 
   4152 	assert((size & pagesize_mask) == 0);
   4153 	assert((alignment & pagesize_mask) == 0);
   4154 
   4155 #ifdef MALLOC_BALANCE
   4156 	arena_lock_balance(arena);
   4157 #else
   4158 	malloc_spin_lock(&arena->lock);
   4159 #endif
   4160 	ret = (void *)arena_run_alloc(arena, NULL, alloc_size, true, false);
   4161 	if (ret == NULL) {
   4162 		malloc_spin_unlock(&arena->lock);
   4163 		return (NULL);
   4164 	}
   4165 
   4166 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
   4167 
   4168 	offset = (uintptr_t)ret & (alignment - 1);
   4169 	assert((offset & pagesize_mask) == 0);
   4170 	assert(offset < alloc_size);
   4171 	if (offset == 0)
   4172 		arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, alloc_size, size, false);
   4173 	else {
   4174 		size_t leadsize, trailsize;
   4175 
   4176 		leadsize = alignment - offset;
   4177 		if (leadsize > 0) {
   4178 			arena_run_trim_head(arena, chunk, (arena_run_t*)ret, alloc_size,
   4179 			    alloc_size - leadsize);
   4180 			ret = (void *)((uintptr_t)ret + leadsize);
   4181 		}
   4182 
   4183 		trailsize = alloc_size - leadsize - size;
   4184 		if (trailsize != 0) {
   4185 			/* Trim trailing space. */
   4186 			assert(trailsize < alloc_size);
   4187 			arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, size + trailsize,
   4188 			    size, false);
   4189 		}
   4190 	}
   4191 
   4192 #ifdef MALLOC_STATS
   4193 	arena->stats.nmalloc_large++;
   4194 	arena->stats.allocated_large += size;
   4195 #endif
   4196 	malloc_spin_unlock(&arena->lock);
   4197 
   4198 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
   4199 #ifdef MALLOC_FILL
   4200 	if (opt_junk)
   4201 		memset(ret, 0xa5, size);
   4202 	else if (opt_zero)
   4203 		memset(ret, 0, size);
   4204 #endif
   4205 	return (ret);
   4206 }
   4207 
   4208 static inline void *
   4209 ipalloc(size_t alignment, size_t size)
   4210 {
   4211 	void *ret;
   4212 	size_t ceil_size;
   4213 
   4214 	/*
   4215 	 * Round size up to the nearest multiple of alignment.
   4216 	 *
   4217 	 * This done, we can take advantage of the fact that for each small
   4218 	 * size class, every object is aligned at the smallest power of two
   4219 	 * that is non-zero in the base two representation of the size.  For
   4220 	 * example:
   4221 	 *
   4222 	 *   Size |   Base 2 | Minimum alignment
   4223 	 *   -----+----------+------------------
   4224 	 *     96 |  1100000 |  32
   4225 	 *    144 | 10100000 |  32
   4226 	 *    192 | 11000000 |  64
   4227 	 *
   4228 	 * Depending on runtime settings, it is possible that arena_malloc()
   4229 	 * will further round up to a power of two, but that never causes
   4230 	 * correctness issues.
   4231 	 */
   4232 	ceil_size = (size + (alignment - 1)) & (-alignment);
   4233 	/*
   4234 	 * (ceil_size < size) protects against the combination of maximal
   4235 	 * alignment and size greater than maximal alignment.
   4236 	 */
   4237 	if (ceil_size < size) {
   4238 		/* size_t overflow. */
   4239 		return (NULL);
   4240 	}
   4241 
   4242 	if (ceil_size <= pagesize || (alignment <= pagesize
   4243 	    && ceil_size <= arena_maxclass))
   4244 		ret = arena_malloc(choose_arena(), ceil_size, false);
   4245 	else {
   4246 		size_t run_size;
   4247 
   4248 		/*
   4249 		 * We can't achieve sub-page alignment, so round up alignment
   4250 		 * permanently; it makes later calculations simpler.
   4251 		 */
   4252 		alignment = PAGE_CEILING(alignment);
   4253 		ceil_size = PAGE_CEILING(size);
   4254 		/*
   4255 		 * (ceil_size < size) protects against very large sizes within
   4256 		 * pagesize of SIZE_T_MAX.
   4257 		 *
   4258 		 * (ceil_size + alignment < ceil_size) protects against the
   4259 		 * combination of maximal alignment and ceil_size large enough
   4260 		 * to cause overflow.  This is similar to the first overflow
   4261 		 * check above, but it needs to be repeated due to the new
   4262 		 * ceil_size value, which may now be *equal* to maximal
   4263 		 * alignment, whereas before we only detected overflow if the
   4264 		 * original size was *greater* than maximal alignment.
   4265 		 */
   4266 		if (ceil_size < size || ceil_size + alignment < ceil_size) {
   4267 			/* size_t overflow. */
   4268 			return (NULL);
   4269 		}
   4270 
   4271 		/*
   4272 		 * Calculate the size of the over-size run that arena_palloc()
   4273 		 * would need to allocate in order to guarantee the alignment.
   4274 		 */
   4275 		if (ceil_size >= alignment)
   4276 			run_size = ceil_size + alignment - pagesize;
   4277 		else {
   4278 			/*
   4279 			 * It is possible that (alignment << 1) will cause
   4280 			 * overflow, but it doesn't matter because we also
   4281 			 * subtract pagesize, which in the case of overflow
   4282 			 * leaves us with a very large run_size.  That causes
   4283 			 * the first conditional below to fail, which means
   4284 			 * that the bogus run_size value never gets used for
   4285 			 * anything important.
   4286 			 */
   4287 			run_size = (alignment << 1) - pagesize;
   4288 		}
   4289 
   4290 		if (run_size <= arena_maxclass) {
   4291 			ret = arena_palloc(choose_arena(), alignment, ceil_size,
   4292 			    run_size);
   4293 		} else if (alignment <= chunksize)
   4294 			ret = huge_malloc(ceil_size, false);
   4295 		else
   4296 			ret = huge_palloc(alignment, ceil_size);
   4297 	}
   4298 
   4299 	assert(((uintptr_t)ret & (alignment - 1)) == 0);
   4300 	return (ret);
   4301 }
   4302 
   4303 /* Return the size of the allocation pointed to by ptr. */
   4304 static size_t
   4305 arena_salloc(const void *ptr)
   4306 {
   4307 	size_t ret;
   4308 	arena_chunk_t *chunk;
   4309 	size_t pageind, mapbits;
   4310 
   4311 	assert(ptr != NULL);
   4312 	assert(CHUNK_ADDR2BASE(ptr) != ptr);
   4313 
   4314 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   4315 	pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow);
   4316 	mapbits = chunk->map[pageind].bits;
   4317 	assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
   4318 	if ((mapbits & CHUNK_MAP_LARGE) == 0) {
   4319 		arena_run_t *run = (arena_run_t *)(mapbits & ~pagesize_mask);
   4320 		assert(run->magic == ARENA_RUN_MAGIC);
   4321 		ret = run->bin->reg_size;
   4322 	} else {
   4323 		ret = mapbits & ~pagesize_mask;
   4324 		assert(ret != 0);
   4325 	}
   4326 
   4327 	return (ret);
   4328 }
   4329 
   4330 #if (defined(MALLOC_VALIDATE) || defined(MOZ_MEMORY_DARWIN))
   4331 /*
   4332  * Validate ptr before assuming that it points to an allocation.  Currently,
   4333  * the following validation is performed:
   4334  *
   4335  * + Check that ptr is not NULL.
   4336  *
   4337  * + Check that ptr lies within a mapped chunk.
   4338  */
   4339 static inline size_t
   4340 isalloc_validate(const void *ptr)
   4341 {
   4342 	arena_chunk_t *chunk;
   4343 
   4344 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   4345 	if (chunk == NULL)
   4346 		return (0);
   4347 
   4348 	if (malloc_rtree_get(chunk_rtree, (uintptr_t)chunk) == NULL)
   4349 		return (0);
   4350 
   4351 	if (chunk != ptr) {
   4352 		assert(chunk->arena->magic == ARENA_MAGIC);
   4353 		return (arena_salloc(ptr));
   4354 	} else {
   4355 		size_t ret;
   4356 		extent_node_t *node;
   4357 		extent_node_t key;
   4358 
   4359 		/* Chunk. */
   4360 		key.addr = (void *)chunk;
   4361 		malloc_mutex_lock(&huge_mtx);
   4362 		node = extent_tree_ad_search(&huge, &key);
   4363 		if (node != NULL)
   4364 			ret = node->size;
   4365 		else
   4366 			ret = 0;
   4367 		malloc_mutex_unlock(&huge_mtx);
   4368 		return (ret);
   4369 	}
   4370 }
   4371 #endif
   4372 
   4373 static inline size_t
   4374 isalloc(const void *ptr)
   4375 {
   4376 	size_t ret;
   4377 	arena_chunk_t *chunk;
   4378 
   4379 	assert(ptr != NULL);
   4380 
   4381 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   4382 	if (chunk != ptr) {
   4383 		/* Region. */
   4384 		assert(chunk->arena->magic == ARENA_MAGIC);
   4385 
   4386 		ret = arena_salloc(ptr);
   4387 	} else {
   4388 		extent_node_t *node, key;
   4389 
   4390 		/* Chunk (huge allocation). */
   4391 
   4392 		malloc_mutex_lock(&huge_mtx);
   4393 
   4394 		/* Extract from tree of huge allocations. */
   4395 		key.addr = __DECONST(void *, ptr);
   4396 		node = extent_tree_ad_search(&huge, &key);
   4397 		assert(node != NULL);
   4398 
   4399 		ret = node->size;
   4400 
   4401 		malloc_mutex_unlock(&huge_mtx);
   4402 	}
   4403 
   4404 	return (ret);
   4405 }
   4406 
   4407 static inline void
   4408 arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
   4409     arena_chunk_map_t *mapelm)
   4410 {
   4411 	arena_run_t *run;
   4412 	arena_bin_t *bin;
   4413 	size_t size;
   4414 
   4415 	run = (arena_run_t *)(mapelm->bits & ~pagesize_mask);
   4416 	assert(run->magic == ARENA_RUN_MAGIC);
   4417 	bin = run->bin;
   4418 	size = bin->reg_size;
   4419 
   4420 #ifdef MALLOC_FILL
   4421 	if (opt_junk)
   4422 		memset(ptr, 0x5a, size);
   4423 #endif
   4424 
   4425 	arena_run_reg_dalloc(run, bin, ptr, size);
   4426 	run->nfree++;
   4427 
   4428 	if (run->nfree == bin->nregs) {
   4429 		/* Deallocate run. */
   4430 		if (run == bin->runcur)
   4431 			bin->runcur = NULL;
   4432 		else if (bin->nregs != 1) {
   4433 			size_t run_pageind = (((uintptr_t)run -
   4434 			    (uintptr_t)chunk)) >> pagesize_2pow;
   4435 			arena_chunk_map_t *run_mapelm =
   4436 			    &chunk->map[run_pageind];
   4437 			/*
   4438 			 * This block's conditional is necessary because if the
   4439 			 * run only contains one region, then it never gets
   4440 			 * inserted into the non-full runs tree.
   4441 			 */
   4442 			assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
   4443 			    run_mapelm);
   4444 			arena_run_tree_remove(&bin->runs, run_mapelm);
   4445 		}
   4446 #ifdef MALLOC_DEBUG
   4447 		run->magic = 0;
   4448 #endif
   4449 		VALGRIND_FREELIKE_BLOCK(run, 0);
   4450 		arena_run_dalloc(arena, run, true);
   4451 #ifdef MALLOC_STATS
   4452 		bin->stats.curruns--;
   4453 #endif
   4454 	} else if (run->nfree == 1 && run != bin->runcur) {
   4455 		/*
   4456 		 * Make sure that bin->runcur always refers to the lowest
   4457 		 * non-full run, if one exists.
   4458 		 */
   4459 		if (bin->runcur == NULL)
   4460 			bin->runcur = run;
   4461 		else if ((uintptr_t)run < (uintptr_t)bin->runcur) {
   4462 			/* Switch runcur. */
   4463 			if (bin->runcur->nfree > 0) {
   4464 				arena_chunk_t *runcur_chunk =
   4465 				    (arena_chunk_t*)CHUNK_ADDR2BASE(bin->runcur);
   4466 				size_t runcur_pageind =
   4467 				    (((uintptr_t)bin->runcur -
   4468 				    (uintptr_t)runcur_chunk)) >> pagesize_2pow;
   4469 				arena_chunk_map_t *runcur_mapelm =
   4470 				    &runcur_chunk->map[runcur_pageind];
   4471 
   4472 				/* Insert runcur. */
   4473 				assert(arena_run_tree_search(&bin->runs,
   4474 				    runcur_mapelm) == NULL);
   4475 				arena_run_tree_insert(&bin->runs,
   4476 				    runcur_mapelm);
   4477 			}
   4478 			bin->runcur = run;
   4479 		} else {
   4480 			size_t run_pageind = (((uintptr_t)run -
   4481 			    (uintptr_t)chunk)) >> pagesize_2pow;
   4482 			arena_chunk_map_t *run_mapelm =
   4483 			    &chunk->map[run_pageind];
   4484 
   4485 			assert(arena_run_tree_search(&bin->runs, run_mapelm) ==
   4486 			    NULL);
   4487 			arena_run_tree_insert(&bin->runs, run_mapelm);
   4488 		}
   4489 	}
   4490 #ifdef MALLOC_STATS
   4491 	arena->stats.allocated_small -= size;
   4492 	arena->stats.ndalloc_small++;
   4493 #endif
   4494 }
   4495 
   4496 static void
   4497 arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
   4498 {
   4499 	/* Large allocation. */
   4500 	malloc_spin_lock(&arena->lock);
   4501 
   4502 #ifdef MALLOC_FILL
   4503 #ifndef MALLOC_STATS
   4504 	if (opt_junk)
   4505 #endif
   4506 #endif
   4507 	{
   4508 		size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>
   4509 		    pagesize_2pow;
   4510 		size_t size = chunk->map[pageind].bits & ~pagesize_mask;
   4511 
   4512 #ifdef MALLOC_FILL
   4513 #ifdef MALLOC_STATS
   4514 		if (opt_junk)
   4515 #endif
   4516 			memset(ptr, 0x5a, size);
   4517 #endif
   4518 #ifdef MALLOC_STATS
   4519 		arena->stats.allocated_large -= size;
   4520 #endif
   4521 	}
   4522 #ifdef MALLOC_STATS
   4523 	arena->stats.ndalloc_large++;
   4524 #endif
   4525 
   4526 	arena_run_dalloc(arena, (arena_run_t *)ptr, true);
   4527 	malloc_spin_unlock(&arena->lock);
   4528 }
   4529 
   4530 static inline void
   4531 arena_dalloc(arena_t *arena, arena_chunk_t *chunk, void *ptr)
   4532 {
   4533 	size_t pageind;
   4534 	arena_chunk_map_t *mapelm;
   4535 
   4536 	assert(arena != NULL);
   4537 	assert(arena->magic == ARENA_MAGIC);
   4538 	assert(chunk->arena == arena);
   4539 	assert(ptr != NULL);
   4540 	assert(CHUNK_ADDR2BASE(ptr) != ptr);
   4541 
   4542 	pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow);
   4543 	mapelm = &chunk->map[pageind];
   4544 	assert((mapelm->bits & CHUNK_MAP_ALLOCATED) != 0);
   4545 	if ((mapelm->bits & CHUNK_MAP_LARGE) == 0) {
   4546 		/* Small allocation. */
   4547 		malloc_spin_lock(&arena->lock);
   4548 		arena_dalloc_small(arena, chunk, ptr, mapelm);
   4549 		malloc_spin_unlock(&arena->lock);
   4550 	} else
   4551 		arena_dalloc_large(arena, chunk, ptr);
   4552 	VALGRIND_FREELIKE_BLOCK(ptr, 0);
   4553 }
   4554 
   4555 static inline void
   4556 idalloc(void *ptr)
   4557 {
   4558 	arena_chunk_t *chunk;
   4559 
   4560 	assert(ptr != NULL);
   4561 
   4562 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   4563 	if (chunk != ptr)
   4564 		arena_dalloc(chunk->arena, chunk, ptr);
   4565 	else
   4566 		huge_dalloc(ptr);
   4567 }
   4568 
   4569 static void
   4570 arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
   4571     size_t size, size_t oldsize)
   4572 {
   4573 
   4574 	assert(size < oldsize);
   4575 
   4576 	/*
   4577 	 * Shrink the run, and make trailing pages available for other
   4578 	 * allocations.
   4579 	 */
   4580 #ifdef MALLOC_BALANCE
   4581 	arena_lock_balance(arena);
   4582 #else
   4583 	malloc_spin_lock(&arena->lock);
   4584 #endif
   4585 	arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
   4586 	    true);
   4587 #ifdef MALLOC_STATS
   4588 	arena->stats.allocated_large -= oldsize - size;
   4589 #endif
   4590 	malloc_spin_unlock(&arena->lock);
   4591 }
   4592 
   4593 static bool
   4594 arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
   4595     size_t size, size_t oldsize)
   4596 {
   4597 	size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow;
   4598 	size_t npages = oldsize >> pagesize_2pow;
   4599 
   4600 	assert(oldsize == (chunk->map[pageind].bits & ~pagesize_mask));
   4601 
   4602 	/* Try to extend the run. */
   4603 	assert(size > oldsize);
   4604 #ifdef MALLOC_BALANCE
   4605 	arena_lock_balance(arena);
   4606 #else
   4607 	malloc_spin_lock(&arena->lock);
   4608 #endif
   4609 	if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits
   4610 	    & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits &
   4611 	    ~pagesize_mask) >= size - oldsize) {
   4612 		/*
   4613 		 * The next run is available and sufficiently large.  Split the
   4614 		 * following run, then merge the first part with the existing
   4615 		 * allocation.
   4616 		 */
   4617 		arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
   4618 		    ((pageind+npages) << pagesize_2pow)), size - oldsize, true,
   4619 		    false);
   4620 
   4621 		chunk->map[pageind].bits = size | CHUNK_MAP_LARGE |
   4622 		    CHUNK_MAP_ALLOCATED;
   4623 		chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE |
   4624 		    CHUNK_MAP_ALLOCATED;
   4625 
   4626 #ifdef MALLOC_STATS
   4627 		arena->stats.allocated_large += size - oldsize;
   4628 #endif
   4629 		malloc_spin_unlock(&arena->lock);
   4630 		return (false);
   4631 	}
   4632 	malloc_spin_unlock(&arena->lock);
   4633 
   4634 	return (true);
   4635 }
   4636 
   4637 /*
   4638  * Try to resize a large allocation, in order to avoid copying.  This will
   4639  * always fail if growing an object, and the following run is already in use.
   4640  */
   4641 static bool
   4642 arena_ralloc_large(void *ptr, size_t size, size_t oldsize)
   4643 {
   4644 	size_t psize;
   4645 
   4646 	psize = PAGE_CEILING(size);
   4647 	if (psize == oldsize) {
   4648 		/* Same size class. */
   4649 #ifdef MALLOC_FILL
   4650 		if (opt_junk && size < oldsize) {
   4651 			memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
   4652 			    size);
   4653 		}
   4654 #endif
   4655 		return (false);
   4656 	} else {
   4657 		arena_chunk_t *chunk;
   4658 		arena_t *arena;
   4659 
   4660 		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   4661 		arena = chunk->arena;
   4662 		assert(arena->magic == ARENA_MAGIC);
   4663 
   4664 		if (psize < oldsize) {
   4665 #ifdef MALLOC_FILL
   4666 			/* Fill before shrinking in order avoid a race. */
   4667 			if (opt_junk) {
   4668 				memset((void *)((uintptr_t)ptr + size), 0x5a,
   4669 				    oldsize - size);
   4670 			}
   4671 #endif
   4672 			arena_ralloc_large_shrink(arena, chunk, ptr, psize,
   4673 			    oldsize);
   4674 			return (false);
   4675 		} else {
   4676 			bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
   4677 			    psize, oldsize);
   4678 #ifdef MALLOC_FILL
   4679 			if (ret == false && opt_zero) {
   4680 				memset((void *)((uintptr_t)ptr + oldsize), 0,
   4681 				    size - oldsize);
   4682 			}
   4683 #endif
   4684 			return (ret);
   4685 		}
   4686 	}
   4687 }
   4688 
   4689 static void *
   4690 arena_ralloc(void *ptr, size_t size, size_t oldsize)
   4691 {
   4692 	void *ret;
   4693 	size_t copysize;
   4694 
   4695 	/* Try to avoid moving the allocation. */
   4696 	if (size < small_min) {
   4697 		if (oldsize < small_min &&
   4698 		    ffs((int)(pow2_ceil(size) >> (TINY_MIN_2POW + 1)))
   4699 		    == ffs((int)(pow2_ceil(oldsize) >> (TINY_MIN_2POW + 1))))
   4700 			goto IN_PLACE; /* Same size class. */
   4701 	} else if (size <= small_max) {
   4702 		if (oldsize >= small_min && oldsize <= small_max &&
   4703 		    (QUANTUM_CEILING(size) >> opt_quantum_2pow)
   4704 		    == (QUANTUM_CEILING(oldsize) >> opt_quantum_2pow))
   4705 			goto IN_PLACE; /* Same size class. */
   4706 	} else if (size <= bin_maxclass) {
   4707 		if (oldsize > small_max && oldsize <= bin_maxclass &&
   4708 		    pow2_ceil(size) == pow2_ceil(oldsize))
   4709 			goto IN_PLACE; /* Same size class. */
   4710 	} else if (oldsize > bin_maxclass && oldsize <= arena_maxclass) {
   4711 		assert(size > bin_maxclass);
   4712 		if (arena_ralloc_large(ptr, size, oldsize) == false)
   4713 			return (ptr);
   4714 	}
   4715 
   4716 	/*
   4717 	 * If we get here, then size and oldsize are different enough that we
   4718 	 * need to move the object.  In that case, fall back to allocating new
   4719 	 * space and copying.
   4720 	 */
   4721 	ret = arena_malloc(choose_arena(), size, false);
   4722 	if (ret == NULL)
   4723 		return (NULL);
   4724 
   4725 	/* Junk/zero-filling were already done by arena_malloc(). */
   4726 	copysize = (size < oldsize) ? size : oldsize;
   4727 #ifdef VM_COPY_MIN
   4728 	if (copysize >= VM_COPY_MIN)
   4729 		pages_copy(ret, ptr, copysize);
   4730 	else
   4731 #endif
   4732 		memcpy(ret, ptr, copysize);
   4733 	idalloc(ptr);
   4734 	return (ret);
   4735 IN_PLACE:
   4736 #ifdef MALLOC_FILL
   4737 	if (opt_junk && size < oldsize)
   4738 		memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
   4739 	else if (opt_zero && size > oldsize)
   4740 		memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize);
   4741 #endif
   4742 	return (ptr);
   4743 }
   4744 
   4745 static inline void *
   4746 iralloc(void *ptr, size_t size)
   4747 {
   4748 	size_t oldsize;
   4749 
   4750 	assert(ptr != NULL);
   4751 	assert(size != 0);
   4752 
   4753 	oldsize = isalloc(ptr);
   4754 
   4755 #ifndef MALLOC_VALGRIND
   4756 	if (size <= arena_maxclass)
   4757 		return (arena_ralloc(ptr, size, oldsize));
   4758 	else
   4759 		return (huge_ralloc(ptr, size, oldsize));
   4760 #else
   4761 	/*
   4762 	 * Valgrind does not provide a public interface for modifying an
   4763 	 * existing allocation, so use malloc/memcpy/free instead.
   4764 	 */
   4765 	{
   4766 		void *ret = imalloc(size);
   4767 		if (ret != NULL) {
   4768 			if (oldsize < size)
   4769 			    memcpy(ret, ptr, oldsize);
   4770 			else
   4771 			    memcpy(ret, ptr, size);
   4772 			idalloc(ptr);
   4773 		}
   4774 		return (ret);
   4775 	}
   4776 #endif
   4777 }
   4778 
   4779 static bool
   4780 arena_new(arena_t *arena)
   4781 {
   4782 	unsigned i;
   4783 	arena_bin_t *bin;
   4784 	size_t pow2_size, prev_run_size;
   4785 
   4786 	if (malloc_spin_init(&arena->lock))
   4787 		return (true);
   4788 
   4789 #ifdef MALLOC_STATS
   4790 	memset(&arena->stats, 0, sizeof(arena_stats_t));
   4791 #endif
   4792 
   4793 	arena->chunk_seq = 0;
   4794 
   4795 	/* Initialize chunks. */
   4796 	arena_chunk_tree_dirty_new(&arena->chunks_dirty);
   4797 	arena->spare = NULL;
   4798 
   4799 	arena->ndirty = 0;
   4800 
   4801 	arena_avail_tree_new(&arena->runs_avail);
   4802 
   4803 #ifdef MALLOC_BALANCE
   4804 	arena->contention = 0;
   4805 #endif
   4806 
   4807 	/* Initialize bins. */
   4808 	prev_run_size = pagesize;
   4809 
   4810 	/* (2^n)-spaced tiny bins. */
   4811 	for (i = 0; i < ntbins; i++) {
   4812 		bin = &arena->bins[i];
   4813 		bin->runcur = NULL;
   4814 		arena_run_tree_new(&bin->runs);
   4815 
   4816 		bin->reg_size = (1U << (TINY_MIN_2POW + i));
   4817 
   4818 		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
   4819 
   4820 #ifdef MALLOC_STATS
   4821 		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
   4822 #endif
   4823 	}
   4824 
   4825 	/* Quantum-spaced bins. */
   4826 	for (; i < ntbins + nqbins; i++) {
   4827 		bin = &arena->bins[i];
   4828 		bin->runcur = NULL;
   4829 		arena_run_tree_new(&bin->runs);
   4830 
   4831 		bin->reg_size = quantum * (i - ntbins + 1);
   4832 
   4833 		pow2_size = pow2_ceil(quantum * (i - ntbins + 1));
   4834 		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
   4835 
   4836 #ifdef MALLOC_STATS
   4837 		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
   4838 #endif
   4839 	}
   4840 
   4841 	/* (2^n)-spaced sub-page bins. */
   4842 	for (; i < ntbins + nqbins + nsbins; i++) {
   4843 		bin = &arena->bins[i];
   4844 		bin->runcur = NULL;
   4845 		arena_run_tree_new(&bin->runs);
   4846 
   4847 		bin->reg_size = (small_max << (i - (ntbins + nqbins) + 1));
   4848 
   4849 		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
   4850 
   4851 #ifdef MALLOC_STATS
   4852 		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
   4853 #endif
   4854 	}
   4855 
   4856 #ifdef MALLOC_DEBUG
   4857 	arena->magic = ARENA_MAGIC;
   4858 #endif
   4859 
   4860 	return (false);
   4861 }
   4862 
   4863 /* Create a new arena and insert it into the arenas array at index ind. */
   4864 static arena_t *
   4865 arenas_extend(unsigned ind)
   4866 {
   4867 	arena_t *ret;
   4868 
   4869 	/* Allocate enough space for trailing bins. */
   4870 	ret = (arena_t *)base_alloc(sizeof(arena_t)
   4871 	    + (sizeof(arena_bin_t) * (ntbins + nqbins + nsbins - 1)));
   4872 	if (ret != NULL && arena_new(ret) == false) {
   4873 		arenas[ind] = ret;
   4874 		return (ret);
   4875 	}
   4876 	/* Only reached if there is an OOM error. */
   4877 
   4878 	/*
   4879 	 * OOM here is quite inconvenient to propagate, since dealing with it
   4880 	 * would require a check for failure in the fast path.  Instead, punt
   4881 	 * by using arenas[0].  In practice, this is an extremely unlikely
   4882 	 * failure.
   4883 	 */
   4884 	_malloc_message(_getprogname(),
   4885 	    ": (malloc) Error initializing arena\n", "", "");
   4886 	if (opt_abort)
   4887 		abort();
   4888 
   4889 	return (arenas[0]);
   4890 }
   4891 
   4892 /*
   4893  * End arena.
   4894  */
   4895 /******************************************************************************/
   4896 /*
   4897  * Begin general internal functions.
   4898  */
   4899 
   4900 static void *
   4901 huge_malloc(size_t size, bool zero)
   4902 {
   4903 	void *ret;
   4904 	size_t csize;
   4905 #ifdef MALLOC_DECOMMIT
   4906 	size_t psize;
   4907 #endif
   4908 	extent_node_t *node;
   4909 
   4910 	/* Allocate one or more contiguous chunks for this request. */
   4911 
   4912 	csize = CHUNK_CEILING(size);
   4913 	if (csize == 0) {
   4914 		/* size is large enough to cause size_t wrap-around. */
   4915 		return (NULL);
   4916 	}
   4917 
   4918 	/* Allocate an extent node with which to track the chunk. */
   4919 	node = base_node_alloc();
   4920 	if (node == NULL)
   4921 		return (NULL);
   4922 
   4923 	ret = chunk_alloc(csize, zero, true);
   4924 	if (ret == NULL) {
   4925 		base_node_dealloc(node);
   4926 		return (NULL);
   4927 	}
   4928 
   4929 	/* Insert node into huge. */
   4930 	node->addr = ret;
   4931 #ifdef MALLOC_DECOMMIT
   4932 	psize = PAGE_CEILING(size);
   4933 	node->size = psize;
   4934 #else
   4935 	node->size = csize;
   4936 #endif
   4937 
   4938 	malloc_mutex_lock(&huge_mtx);
   4939 	extent_tree_ad_insert(&huge, node);
   4940 #ifdef MALLOC_STATS
   4941 	huge_nmalloc++;
   4942 #  ifdef MALLOC_DECOMMIT
   4943 	huge_allocated += psize;
   4944 #  else
   4945 	huge_allocated += csize;
   4946 #  endif
   4947 #endif
   4948 	malloc_mutex_unlock(&huge_mtx);
   4949 
   4950 #ifdef MALLOC_DECOMMIT
   4951 	if (csize - psize > 0)
   4952 		pages_decommit((void *)((uintptr_t)ret + psize), csize - psize);
   4953 #endif
   4954 
   4955 #ifdef MALLOC_DECOMMIT
   4956 	VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, zero);
   4957 #else
   4958 	VALGRIND_MALLOCLIKE_BLOCK(ret, csize, 0, zero);
   4959 #endif
   4960 
   4961 #ifdef MALLOC_FILL
   4962 	if (zero == false) {
   4963 		if (opt_junk)
   4964 #  ifdef MALLOC_DECOMMIT
   4965 			memset(ret, 0xa5, psize);
   4966 #  else
   4967 			memset(ret, 0xa5, csize);
   4968 #  endif
   4969 		else if (opt_zero)
   4970 #  ifdef MALLOC_DECOMMIT
   4971 			memset(ret, 0, psize);
   4972 #  else
   4973 			memset(ret, 0, csize);
   4974 #  endif
   4975 	}
   4976 #endif
   4977 
   4978 	return (ret);
   4979 }
   4980 
   4981 /* Only handles large allocations that require more than chunk alignment. */
   4982 static void *
   4983 huge_palloc(size_t alignment, size_t size)
   4984 {
   4985 	void *ret;
   4986 	size_t alloc_size, chunk_size, offset;
   4987 #ifdef MALLOC_DECOMMIT
   4988 	size_t psize;
   4989 #endif
   4990 	extent_node_t *node;
   4991 	int pfd;
   4992 
   4993 	/*
   4994 	 * This allocation requires alignment that is even larger than chunk
   4995 	 * alignment.  This means that huge_malloc() isn't good enough.
   4996 	 *
   4997 	 * Allocate almost twice as many chunks as are demanded by the size or
   4998 	 * alignment, in order to assure the alignment can be achieved, then
   4999 	 * unmap leading and trailing chunks.
   5000 	 */
   5001 	assert(alignment >= chunksize);
   5002 
   5003 	chunk_size = CHUNK_CEILING(size);
   5004 
   5005 	if (size >= alignment)
   5006 		alloc_size = chunk_size + alignment - chunksize;
   5007 	else
   5008 		alloc_size = (alignment << 1) - chunksize;
   5009 
   5010 	/* Allocate an extent node with which to track the chunk. */
   5011 	node = base_node_alloc();
   5012 	if (node == NULL)
   5013 		return (NULL);
   5014 
   5015 	/*
   5016 	 * Windows requires that there be a 1:1 mapping between VM
   5017 	 * allocation/deallocation operations.  Therefore, take care here to
   5018 	 * acquire the final result via one mapping operation.
   5019 	 *
   5020 	 * The MALLOC_PAGEFILE code also benefits from this mapping algorithm,
   5021 	 * since it reduces the number of page files.
   5022 	 */
   5023 #ifdef MALLOC_PAGEFILE
   5024 	if (opt_pagefile) {
   5025 		pfd = pagefile_init(size);
   5026 		if (pfd == -1)
   5027 			return (NULL);
   5028 	} else
   5029 #endif
   5030 		pfd = -1;
   5031 #ifdef JEMALLOC_USES_MAP_ALIGN
   5032 		ret = pages_map_align(chunk_size, pfd, alignment);
   5033 #else
   5034 	do {
   5035 		void *over;
   5036 
   5037 		over = chunk_alloc(alloc_size, false, false);
   5038 		if (over == NULL) {
   5039 			base_node_dealloc(node);
   5040 			ret = NULL;
   5041 			goto RETURN;
   5042 		}
   5043 
   5044 		offset = (uintptr_t)over & (alignment - 1);
   5045 		assert((offset & chunksize_mask) == 0);
   5046 		assert(offset < alloc_size);
   5047 		ret = (void *)((uintptr_t)over + offset);
   5048 		chunk_dealloc(over, alloc_size);
   5049 		ret = pages_map(ret, chunk_size, pfd);
   5050 		/*
   5051 		 * Failure here indicates a race with another thread, so try
   5052 		 * again.
   5053 		 */
   5054 	} while (ret == NULL);
   5055 #endif
   5056 	/* Insert node into huge. */
   5057 	node->addr = ret;
   5058 #ifdef MALLOC_DECOMMIT
   5059 	psize = PAGE_CEILING(size);
   5060 	node->size = psize;
   5061 #else
   5062 	node->size = chunk_size;
   5063 #endif
   5064 
   5065 	malloc_mutex_lock(&huge_mtx);
   5066 	extent_tree_ad_insert(&huge, node);
   5067 #ifdef MALLOC_STATS
   5068 	huge_nmalloc++;
   5069 #  ifdef MALLOC_DECOMMIT
   5070 	huge_allocated += psize;
   5071 #  else
   5072 	huge_allocated += chunk_size;
   5073 #  endif
   5074 #endif
   5075 	malloc_mutex_unlock(&huge_mtx);
   5076 
   5077 #ifdef MALLOC_DECOMMIT
   5078 	if (chunk_size - psize > 0) {
   5079 		pages_decommit((void *)((uintptr_t)ret + psize),
   5080 		    chunk_size - psize);
   5081 	}
   5082 #endif
   5083 
   5084 #ifdef MALLOC_DECOMMIT
   5085 	VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, false);
   5086 #else
   5087 	VALGRIND_MALLOCLIKE_BLOCK(ret, chunk_size, 0, false);
   5088 #endif
   5089 
   5090 #ifdef MALLOC_FILL
   5091 	if (opt_junk)
   5092 #  ifdef MALLOC_DECOMMIT
   5093 		memset(ret, 0xa5, psize);
   5094 #  else
   5095 		memset(ret, 0xa5, chunk_size);
   5096 #  endif
   5097 	else if (opt_zero)
   5098 #  ifdef MALLOC_DECOMMIT
   5099 		memset(ret, 0, psize);
   5100 #  else
   5101 		memset(ret, 0, chunk_size);
   5102 #  endif
   5103 #endif
   5104 
   5105 RETURN:
   5106 #ifdef MALLOC_PAGEFILE
   5107 	if (pfd != -1)
   5108 		pagefile_close(pfd);
   5109 #endif
   5110 	return (ret);
   5111 }
   5112 
   5113 static void *
   5114 huge_ralloc(void *ptr, size_t size, size_t oldsize)
   5115 {
   5116 	void *ret;
   5117 	size_t copysize;
   5118 
   5119 	/* Avoid moving the allocation if the size class would not change. */
   5120 
   5121 	if (oldsize > arena_maxclass &&
   5122 	    CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) {
   5123 #ifdef MALLOC_DECOMMIT
   5124 		size_t psize = PAGE_CEILING(size);
   5125 #endif
   5126 #ifdef MALLOC_FILL
   5127 		if (opt_junk && size < oldsize) {
   5128 			memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize
   5129 			    - size);
   5130 		}
   5131 #endif
   5132 #ifdef MALLOC_DECOMMIT
   5133 		if (psize < oldsize) {
   5134 			extent_node_t *node, key;
   5135 
   5136 			pages_decommit((void *)((uintptr_t)ptr + psize),
   5137 			    oldsize - psize);
   5138 
   5139 			/* Update recorded size. */
   5140 			malloc_mutex_lock(&huge_mtx);
   5141 			key.addr = __DECONST(void *, ptr);
   5142 			node = extent_tree_ad_search(&huge, &key);
   5143 			assert(node != NULL);
   5144 			assert(node->size == oldsize);
   5145 #  ifdef MALLOC_STATS
   5146 			huge_allocated -= oldsize - psize;
   5147 #  endif
   5148 			node->size = psize;
   5149 			malloc_mutex_unlock(&huge_mtx);
   5150 		} else if (psize > oldsize) {
   5151 			extent_node_t *node, key;
   5152 
   5153 			pages_commit((void *)((uintptr_t)ptr + oldsize),
   5154 			    psize - oldsize);
   5155 
   5156 			/* Update recorded size. */
   5157 			malloc_mutex_lock(&huge_mtx);
   5158 			key.addr = __DECONST(void *, ptr);
   5159 			node = extent_tree_ad_search(&huge, &key);
   5160 			assert(node != NULL);
   5161 			assert(node->size == oldsize);
   5162 #  ifdef MALLOC_STATS
   5163 			huge_allocated += psize - oldsize;
   5164 #  endif
   5165 			node->size = psize;
   5166 			malloc_mutex_unlock(&huge_mtx);
   5167 		}
   5168 #endif
   5169 #ifdef MALLOC_FILL
   5170 		if (opt_zero && size > oldsize) {
   5171 			memset((void *)((uintptr_t)ptr + oldsize), 0, size
   5172 			    - oldsize);
   5173 		}
   5174 #endif
   5175 		return (ptr);
   5176 	}
   5177 
   5178 	/*
   5179 	 * If we get here, then size and oldsize are different enough that we
   5180 	 * need to use a different size class.  In that case, fall back to
   5181 	 * allocating new space and copying.
   5182 	 */
   5183 	ret = huge_malloc(size, false);
   5184 	if (ret == NULL)
   5185 		return (NULL);
   5186 
   5187 	copysize = (size < oldsize) ? size : oldsize;
   5188 #ifdef VM_COPY_MIN
   5189 	if (copysize >= VM_COPY_MIN)
   5190 		pages_copy(ret, ptr, copysize);
   5191 	else
   5192 #endif
   5193 		memcpy(ret, ptr, copysize);
   5194 	idalloc(ptr);
   5195 	return (ret);
   5196 }
   5197 
   5198 static void
   5199 huge_dalloc(void *ptr)
   5200 {
   5201 	extent_node_t *node, key;
   5202 
   5203 	malloc_mutex_lock(&huge_mtx);
   5204 
   5205 	/* Extract from tree of huge allocations. */
   5206 	key.addr = ptr;
   5207 	node = extent_tree_ad_search(&huge, &key);
   5208 	assert(node != NULL);
   5209 	assert(node->addr == ptr);
   5210 	extent_tree_ad_remove(&huge, node);
   5211 
   5212 #ifdef MALLOC_STATS
   5213 	huge_ndalloc++;
   5214 	huge_allocated -= node->size;
   5215 #endif
   5216 
   5217 	malloc_mutex_unlock(&huge_mtx);
   5218 
   5219 	/* Unmap chunk. */
   5220 #ifdef MALLOC_FILL
   5221 	if (opt_junk)
   5222 		memset(node->addr, 0x5a, node->size);
   5223 #endif
   5224 #ifdef MALLOC_DECOMMIT
   5225 	chunk_dealloc(node->addr, CHUNK_CEILING(node->size));
   5226 #else
   5227 	chunk_dealloc(node->addr, node->size);
   5228 #endif
   5229 	VALGRIND_FREELIKE_BLOCK(node->addr, 0);
   5230 
   5231 	base_node_dealloc(node);
   5232 }
   5233 
   5234 #ifdef MOZ_MEMORY_BSD
   5235 static inline unsigned
   5236 malloc_ncpus(void)
   5237 {
   5238 	unsigned ret;
   5239 	int mib[2];
   5240 	size_t len;
   5241 
   5242 	mib[0] = CTL_HW;
   5243 	mib[1] = HW_NCPU;
   5244 	len = sizeof(ret);
   5245 	if (sysctl(mib, 2, &ret, &len, (void *) 0, 0) == -1) {
   5246 		/* Error. */
   5247 		return (1);
   5248 	}
   5249 
   5250 	return (ret);
   5251 }
   5252 #elif (defined(MOZ_MEMORY_LINUX))
   5253 #include <fcntl.h>
   5254 
   5255 static inline unsigned
   5256 malloc_ncpus(void)
   5257 {
   5258 	unsigned ret;
   5259 	int fd, nread, column;
   5260 	char buf[1024];
   5261 	static const char matchstr[] = "processor\t:";
   5262 	int i;
   5263 
   5264 	/*
   5265 	 * sysconf(3) would be the preferred method for determining the number
   5266 	 * of CPUs, but it uses malloc internally, which causes untennable
   5267 	 * recursion during malloc initialization.
   5268 	 */
   5269 	fd = open("/proc/cpuinfo", O_RDONLY);
   5270 	if (fd == -1)
   5271 		return (1); /* Error. */
   5272 	/*
   5273 	 * Count the number of occurrences of matchstr at the beginnings of
   5274 	 * lines.  This treats hyperthreaded CPUs as multiple processors.
   5275 	 */
   5276 	column = 0;
   5277 	ret = 0;
   5278 	while (true) {
   5279 		nread = read(fd, &buf, sizeof(buf));
   5280 		if (nread <= 0)
   5281 			break; /* EOF or error. */
   5282 		for (i = 0;i < nread;i++) {
   5283 			char c = buf[i];
   5284 			if (c == '\n')
   5285 				column = 0;
   5286 			else if (column != -1) {
   5287 				if (c == matchstr[column]) {
   5288 					column++;
   5289 					if (column == sizeof(matchstr) - 1) {
   5290 						column = -1;
   5291 						ret++;
   5292 					}
   5293 				} else
   5294 					column = -1;
   5295 			}
   5296 		}
   5297 	}
   5298 
   5299 	if (ret == 0)
   5300 		ret = 1; /* Something went wrong in the parser. */
   5301 	close(fd);
   5302 
   5303 	return (ret);
   5304 }
   5305 #elif (defined(MOZ_MEMORY_DARWIN))
   5306 #include <mach/mach_init.h>
   5307 #include <mach/mach_host.h>
   5308 
   5309 static inline unsigned
   5310 malloc_ncpus(void)
   5311 {
   5312 	kern_return_t error;
   5313 	natural_t n;
   5314 	processor_info_array_t pinfo;
   5315 	mach_msg_type_number_t pinfocnt;
   5316 
   5317 	error = host_processor_info(mach_host_self(), PROCESSOR_BASIC_INFO,
   5318 				    &n, &pinfo, &pinfocnt);
   5319 	if (error != KERN_SUCCESS)
   5320 		return (1); /* Error. */
   5321 	else
   5322 		return (n);
   5323 }
   5324 #elif (defined(MOZ_MEMORY_SOLARIS))
   5325 
   5326 static inline unsigned
   5327 malloc_ncpus(void)
   5328 {
   5329 	return sysconf(_SC_NPROCESSORS_ONLN);
   5330 }
   5331 #else
   5332 static inline unsigned
   5333 malloc_ncpus(void)
   5334 {
   5335 
   5336 	/*
   5337 	 * We lack a way to determine the number of CPUs on this platform, so
   5338 	 * assume 1 CPU.
   5339 	 */
   5340 	return (1);
   5341 }
   5342 #endif
   5343 
   5344 static void
   5345 malloc_print_stats(void)
   5346 {
   5347 
   5348 	if (opt_print_stats) {
   5349 		char s[UMAX2S_BUFSIZE];
   5350 		_malloc_message("___ Begin malloc statistics ___\n", "", "",
   5351 		    "");
   5352 		_malloc_message("Assertions ",
   5353 #ifdef NDEBUG
   5354 		    "disabled",
   5355 #else
   5356 		    "enabled",
   5357 #endif
   5358 		    "\n", "");
   5359 		_malloc_message("Boolean MALLOC_OPTIONS: ",
   5360 		    opt_abort ? "A" : "a", "", "");
   5361 #ifdef MALLOC_FILL
   5362 		_malloc_message(opt_junk ? "J" : "j", "", "", "");
   5363 #endif
   5364 #ifdef MALLOC_PAGEFILE
   5365 		_malloc_message(opt_pagefile ? "o" : "O", "", "", "");
   5366 #endif
   5367 		_malloc_message("P", "", "", "");
   5368 #ifdef MALLOC_UTRACE
   5369 		_malloc_message(opt_utrace ? "U" : "u", "", "", "");
   5370 #endif
   5371 #ifdef MALLOC_SYSV
   5372 		_malloc_message(opt_sysv ? "V" : "v", "", "", "");
   5373 #endif
   5374 #ifdef MALLOC_XMALLOC
   5375 		_malloc_message(opt_xmalloc ? "X" : "x", "", "", "");
   5376 #endif
   5377 #ifdef MALLOC_FILL
   5378 		_malloc_message(opt_zero ? "Z" : "z", "", "", "");
   5379 #endif
   5380 		_malloc_message("\n", "", "", "");
   5381 
   5382 		_malloc_message("CPUs: ", umax2s(ncpus, s), "\n", "");
   5383 		_malloc_message("Max arenas: ", umax2s(narenas, s), "\n", "");
   5384 #ifdef MALLOC_BALANCE
   5385 		_malloc_message("Arena balance threshold: ",
   5386 		    umax2s(opt_balance_threshold, s), "\n", "");
   5387 #endif
   5388 		_malloc_message("Pointer size: ", umax2s(sizeof(void *), s),
   5389 		    "\n", "");
   5390 		_malloc_message("Quantum size: ", umax2s(quantum, s), "\n", "");
   5391 		_malloc_message("Max small size: ", umax2s(small_max, s), "\n",
   5392 		    "");
   5393 		_malloc_message("Max dirty pages per arena: ",
   5394 		    umax2s(opt_dirty_max, s), "\n", "");
   5395 
   5396 		_malloc_message("Chunk size: ", umax2s(chunksize, s), "", "");
   5397 		_malloc_message(" (2^", umax2s(opt_chunk_2pow, s), ")\n", "");
   5398 
   5399 #ifdef MALLOC_STATS
   5400 		{
   5401 			size_t allocated, mapped;
   5402 #ifdef MALLOC_BALANCE
   5403 			uint64_t nbalance = 0;
   5404 #endif
   5405 			unsigned i;
   5406 			arena_t *arena;
   5407 
   5408 			/* Calculate and print allocated/mapped stats. */
   5409 
   5410 			/* arenas. */
   5411 			for (i = 0, allocated = 0; i < narenas; i++) {
   5412 				if (arenas[i] != NULL) {
   5413 					malloc_spin_lock(&arenas[i]->lock);
   5414 					allocated +=
   5415 					    arenas[i]->stats.allocated_small;
   5416 					allocated +=
   5417 					    arenas[i]->stats.allocated_large;
   5418 #ifdef MALLOC_BALANCE
   5419 					nbalance += arenas[i]->stats.nbalance;
   5420 #endif
   5421 					malloc_spin_unlock(&arenas[i]->lock);
   5422 				}
   5423 			}
   5424 
   5425 			/* huge/base. */
   5426 			malloc_mutex_lock(&huge_mtx);
   5427 			allocated += huge_allocated;
   5428 			mapped = stats_chunks.curchunks * chunksize;
   5429 			malloc_mutex_unlock(&huge_mtx);
   5430 
   5431 			malloc_mutex_lock(&base_mtx);
   5432 			mapped += base_mapped;
   5433 			malloc_mutex_unlock(&base_mtx);
   5434 
   5435 #ifdef MOZ_MEMORY_WINDOWS
   5436 			malloc_printf("Allocated: %lu, mapped: %lu\n",
   5437 			    allocated, mapped);
   5438 #else
   5439 			malloc_printf("Allocated: %zu, mapped: %zu\n",
   5440 			    allocated, mapped);
   5441 #endif
   5442 
   5443 			malloc_mutex_lock(&reserve_mtx);
   5444 			malloc_printf("Reserve:    min          "
   5445 			    "cur          max\n");
   5446 #ifdef MOZ_MEMORY_WINDOWS
   5447 			malloc_printf("   %12lu %12lu %12lu\n",
   5448 			    CHUNK_CEILING(reserve_min) >> opt_chunk_2pow,
   5449 			    reserve_cur >> opt_chunk_2pow,
   5450 			    reserve_max >> opt_chunk_2pow);
   5451 #else
   5452 			malloc_printf("   %12zu %12zu %12zu\n",
   5453 			    CHUNK_CEILING(reserve_min) >> opt_chunk_2pow,
   5454 			    reserve_cur >> opt_chunk_2pow,
   5455 			    reserve_max >> opt_chunk_2pow);
   5456 #endif
   5457 			malloc_mutex_unlock(&reserve_mtx);
   5458 
   5459 #ifdef MALLOC_BALANCE
   5460 			malloc_printf("Arena balance reassignments: %llu\n",
   5461 			    nbalance);
   5462 #endif
   5463 
   5464 			/* Print chunk stats. */
   5465 			{
   5466 				chunk_stats_t chunks_stats;
   5467 
   5468 				malloc_mutex_lock(&huge_mtx);
   5469 				chunks_stats = stats_chunks;
   5470 				malloc_mutex_unlock(&huge_mtx);
   5471 
   5472 				malloc_printf("chunks: nchunks   "
   5473 				    "highchunks    curchunks\n");
   5474 				malloc_printf("  %13llu%13lu%13lu\n",
   5475 				    chunks_stats.nchunks,
   5476 				    chunks_stats.highchunks,
   5477 				    chunks_stats.curchunks);
   5478 			}
   5479 
   5480 			/* Print chunk stats. */
   5481 			malloc_printf(
   5482 			    "huge: nmalloc      ndalloc    allocated\n");
   5483 #ifdef MOZ_MEMORY_WINDOWS
   5484 			malloc_printf(" %12llu %12llu %12lu\n",
   5485 			    huge_nmalloc, huge_ndalloc, huge_allocated);
   5486 #else
   5487 			malloc_printf(" %12llu %12llu %12zu\n",
   5488 			    huge_nmalloc, huge_ndalloc, huge_allocated);
   5489 #endif
   5490 			/* Print stats for each arena. */
   5491 			for (i = 0; i < narenas; i++) {
   5492 				arena = arenas[i];
   5493 				if (arena != NULL) {
   5494 					malloc_printf(
   5495 					    "\narenas[%u]:\n", i);
   5496 					malloc_spin_lock(&arena->lock);
   5497 					stats_print(arena);
   5498 					malloc_spin_unlock(&arena->lock);
   5499 				}
   5500 			}
   5501 		}
   5502 #endif /* #ifdef MALLOC_STATS */
   5503 		_malloc_message("--- End malloc statistics ---\n", "", "", "");
   5504 	}
   5505 }
   5506 
   5507 /*
   5508  * FreeBSD's pthreads implementation calls malloc(3), so the malloc
   5509  * implementation has to take pains to avoid infinite recursion during
   5510  * initialization.
   5511  */
   5512 #if (defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_DARWIN)) && !defined(MOZ_MEMORY_WINCE)
   5513 #define	malloc_init() false
   5514 #else
   5515 static inline bool
   5516 malloc_init(void)
   5517 {
   5518 
   5519 	if (malloc_initialized == false)
   5520 		return (malloc_init_hard());
   5521 
   5522 	return (false);
   5523 }
   5524 #endif
   5525 
   5526 #if !defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_WINCE)
   5527 static
   5528 #endif
   5529 bool
   5530 malloc_init_hard(void)
   5531 {
   5532 	unsigned i;
   5533 	char buf[PATH_MAX + 1];
   5534 	const char *opts;
   5535 	long result;
   5536 #ifndef MOZ_MEMORY_WINDOWS
   5537 	int linklen;
   5538 #endif
   5539 
   5540 #ifndef MOZ_MEMORY_WINDOWS
   5541 	malloc_mutex_lock(&init_lock);
   5542 #endif
   5543 
   5544 	if (malloc_initialized) {
   5545 		/*
   5546 		 * Another thread initialized the allocator before this one
   5547 		 * acquired init_lock.
   5548 		 */
   5549 #ifndef MOZ_MEMORY_WINDOWS
   5550 		malloc_mutex_unlock(&init_lock);
   5551 #endif
   5552 		return (false);
   5553 	}
   5554 
   5555 #ifdef MOZ_MEMORY_WINDOWS
   5556 	/* get a thread local storage index */
   5557 	tlsIndex = TlsAlloc();
   5558 #endif
   5559 
   5560 	/* Get page size and number of CPUs */
   5561 #ifdef MOZ_MEMORY_WINDOWS
   5562 	{
   5563 		SYSTEM_INFO info;
   5564 
   5565 		GetSystemInfo(&info);
   5566 		result = info.dwPageSize;
   5567 
   5568 		pagesize = (unsigned) result;
   5569 
   5570 		ncpus = info.dwNumberOfProcessors;
   5571 	}
   5572 #else
   5573 	ncpus = malloc_ncpus();
   5574 
   5575 	result = sysconf(_SC_PAGESIZE);
   5576 	assert(result != -1);
   5577 
   5578 	pagesize = (unsigned) result;
   5579 #endif
   5580 
   5581 	/*
   5582 	 * We assume that pagesize is a power of 2 when calculating
   5583 	 * pagesize_mask and pagesize_2pow.
   5584 	 */
   5585 	assert(((result - 1) & result) == 0);
   5586 	pagesize_mask = result - 1;
   5587 	pagesize_2pow = ffs((int)result) - 1;
   5588 
   5589 #ifdef MALLOC_PAGEFILE
   5590 	/*
   5591 	 * Determine where to create page files.  It is insufficient to
   5592 	 * unconditionally use P_tmpdir (typically "/tmp"), since for some
   5593 	 * operating systems /tmp is a separate filesystem that is rather small.
   5594 	 * Therefore prefer, in order, the following locations:
   5595 	 *
   5596 	 * 1) MALLOC_TMPDIR
   5597 	 * 2) TMPDIR
   5598 	 * 3) P_tmpdir
   5599 	 */
   5600 	{
   5601 		char *s;
   5602 		size_t slen;
   5603 		static const char suffix[] = "/jemalloc.XXXXXX";
   5604 
   5605 		if ((s = getenv("MALLOC_TMPDIR")) == NULL && (s =
   5606 		    getenv("TMPDIR")) == NULL)
   5607 			s = P_tmpdir;
   5608 		slen = strlen(s);
   5609 		if (slen + sizeof(suffix) > sizeof(pagefile_templ)) {
   5610 			_malloc_message(_getprogname(),
   5611 			    ": (malloc) Page file path too long\n",
   5612 			    "", "");
   5613 			abort();
   5614 		}
   5615 		memcpy(pagefile_templ, s, slen);
   5616 		memcpy(&pagefile_templ[slen], suffix, sizeof(suffix));
   5617 	}
   5618 #endif
   5619 
   5620 	for (i = 0; i < 3; i++) {
   5621 		unsigned j;
   5622 
   5623 		/* Get runtime configuration. */
   5624 		switch (i) {
   5625 		case 0:
   5626 #ifndef MOZ_MEMORY_WINDOWS
   5627 			if ((linklen = readlink("/etc/malloc.conf", buf,
   5628 						sizeof(buf) - 1)) != -1) {
   5629 				/*
   5630 				 * Use the contents of the "/etc/malloc.conf"
   5631 				 * symbolic link's name.
   5632 				 */
   5633 				buf[linklen] = '\0';
   5634 				opts = buf;
   5635 			} else
   5636 #endif
   5637 			{
   5638 				/* No configuration specified. */
   5639 				buf[0] = '\0';
   5640 				opts = buf;
   5641 			}
   5642 			break;
   5643 		case 1:
   5644 			if (issetugid() == 0 && (opts =
   5645 			    getenv("MALLOC_OPTIONS")) != NULL) {
   5646 				/*
   5647 				 * Do nothing; opts is already initialized to
   5648 				 * the value of the MALLOC_OPTIONS environment
   5649 				 * variable.
   5650 				 */
   5651 			} else {
   5652 				/* No configuration specified. */
   5653 				buf[0] = '\0';
   5654 				opts = buf;
   5655 			}
   5656 			break;
   5657 		case 2:
   5658 			if (_malloc_options != NULL) {
   5659 				/*
   5660 				 * Use options that were compiled into the
   5661 				 * program.
   5662 				 */
   5663 				opts = _malloc_options;
   5664 			} else {
   5665 				/* No configuration specified. */
   5666 				buf[0] = '\0';
   5667 				opts = buf;
   5668 			}
   5669 			break;
   5670 		default:
   5671 			/* NOTREACHED */
   5672 			buf[0] = '\0';
   5673 			opts = buf;
   5674 			assert(false);
   5675 		}
   5676 
   5677 		for (j = 0; opts[j] != '\0'; j++) {
   5678 			unsigned k, nreps;
   5679 			bool nseen;
   5680 
   5681 			/* Parse repetition count, if any. */
   5682 			for (nreps = 0, nseen = false;; j++, nseen = true) {
   5683 				switch (opts[j]) {
   5684 					case '0': case '1': case '2': case '3':
   5685 					case '4': case '5': case '6': case '7':
   5686 					case '8': case '9':
   5687 						nreps *= 10;
   5688 						nreps += opts[j] - '0';
   5689 						break;
   5690 					default:
   5691 						goto MALLOC_OUT;
   5692 				}
   5693 			}
   5694 MALLOC_OUT:
   5695 			if (nseen == false)
   5696 				nreps = 1;
   5697 
   5698 			for (k = 0; k < nreps; k++) {
   5699 				switch (opts[j]) {
   5700 				case 'a':
   5701 					opt_abort = false;
   5702 					break;
   5703 				case 'A':
   5704 					opt_abort = true;
   5705 					break;
   5706 				case 'b':
   5707 #ifdef MALLOC_BALANCE
   5708 					opt_balance_threshold >>= 1;
   5709 #endif
   5710 					break;
   5711 				case 'B':
   5712 #ifdef MALLOC_BALANCE
   5713 					if (opt_balance_threshold == 0)
   5714 						opt_balance_threshold = 1;
   5715 					else if ((opt_balance_threshold << 1)
   5716 					    > opt_balance_threshold)
   5717 						opt_balance_threshold <<= 1;
   5718 #endif
   5719 					break;
   5720 				case 'f':
   5721 					opt_dirty_max >>= 1;
   5722 					break;
   5723 				case 'F':
   5724 					if (opt_dirty_max == 0)
   5725 						opt_dirty_max = 1;
   5726 					else if ((opt_dirty_max << 1) != 0)
   5727 						opt_dirty_max <<= 1;
   5728 					break;
   5729 				case 'g':
   5730 					opt_reserve_range_lshift--;
   5731 					break;
   5732 				case 'G':
   5733 					opt_reserve_range_lshift++;
   5734 					break;
   5735 #ifdef MALLOC_FILL
   5736 				case 'j':
   5737 					opt_junk = false;
   5738 					break;
   5739 				case 'J':
   5740 					opt_junk = true;
   5741 					break;
   5742 #endif
   5743 				case 'k':
   5744 					/*
   5745 					 * Chunks always require at least one
   5746 					 * header page, so chunks can never be
   5747 					 * smaller than two pages.
   5748 					 */
   5749 					if (opt_chunk_2pow > pagesize_2pow + 1)
   5750 						opt_chunk_2pow--;
   5751 					break;
   5752 				case 'K':
   5753 					if (opt_chunk_2pow + 1 <
   5754 					    (sizeof(size_t) << 3))
   5755 						opt_chunk_2pow++;
   5756 					break;
   5757 				case 'n':
   5758 					opt_narenas_lshift--;
   5759 					break;
   5760 				case 'N':
   5761 					opt_narenas_lshift++;
   5762 					break;
   5763 #ifdef MALLOC_PAGEFILE
   5764 				case 'o':
   5765 					/* Do not over-commit. */
   5766 					opt_pagefile = true;
   5767 					break;
   5768 				case 'O':
   5769 					/* Allow over-commit. */
   5770 					opt_pagefile = false;
   5771 					break;
   5772 #endif
   5773 				case 'p':
   5774 					opt_print_stats = false;
   5775 					break;
   5776 				case 'P':
   5777 					opt_print_stats = true;
   5778 					break;
   5779 				case 'q':
   5780 					if (opt_quantum_2pow > QUANTUM_2POW_MIN)
   5781 						opt_quantum_2pow--;
   5782 					break;
   5783 				case 'Q':
   5784 					if (opt_quantum_2pow < pagesize_2pow -
   5785 					    1)
   5786 						opt_quantum_2pow++;
   5787 					break;
   5788 				case 'r':
   5789 					opt_reserve_min_lshift--;
   5790 					break;
   5791 				case 'R':
   5792 					opt_reserve_min_lshift++;
   5793 					break;
   5794 				case 's':
   5795 					if (opt_small_max_2pow >
   5796 					    QUANTUM_2POW_MIN)
   5797 						opt_small_max_2pow--;
   5798 					break;
   5799 				case 'S':
   5800 					if (opt_small_max_2pow < pagesize_2pow
   5801 					    - 1)
   5802 						opt_small_max_2pow++;
   5803 					break;
   5804 #ifdef MALLOC_UTRACE
   5805 				case 'u':
   5806 					opt_utrace = false;
   5807 					break;
   5808 				case 'U':
   5809 					opt_utrace = true;
   5810 					break;
   5811 #endif
   5812 #ifdef MALLOC_SYSV
   5813 				case 'v':
   5814 					opt_sysv = false;
   5815 					break;
   5816 				case 'V':
   5817 					opt_sysv = true;
   5818 					break;
   5819 #endif
   5820 #ifdef MALLOC_XMALLOC
   5821 				case 'x':
   5822 					opt_xmalloc = false;
   5823 					break;
   5824 				case 'X':
   5825 					opt_xmalloc = true;
   5826 					break;
   5827 #endif
   5828 #ifdef MALLOC_FILL
   5829 				case 'z':
   5830 					opt_zero = false;
   5831 					break;
   5832 				case 'Z':
   5833 					opt_zero = true;
   5834 					break;
   5835 #endif
   5836 				default: {
   5837 					char cbuf[2];
   5838 
   5839 					cbuf[0] = opts[j];
   5840 					cbuf[1] = '\0';
   5841 					_malloc_message(_getprogname(),
   5842 					    ": (malloc) Unsupported character "
   5843 					    "in malloc options: '", cbuf,
   5844 					    "'\n");
   5845 				}
   5846 				}
   5847 			}
   5848 		}
   5849 	}
   5850 
   5851 	/* Take care to call atexit() only once. */
   5852 	if (opt_print_stats) {
   5853 #ifndef MOZ_MEMORY_WINDOWS
   5854 		/* Print statistics at exit. */
   5855 		atexit(malloc_print_stats);
   5856 #endif
   5857 	}
   5858 
   5859 #if (!defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN))
   5860 	/* Prevent potential deadlock on malloc locks after fork. */
   5861 	pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork);
   5862 #endif
   5863 
   5864 	/* Set variables according to the value of opt_small_max_2pow. */
   5865 	if (opt_small_max_2pow < opt_quantum_2pow)
   5866 		opt_small_max_2pow = opt_quantum_2pow;
   5867 	small_max = (1U << opt_small_max_2pow);
   5868 
   5869 	/* Set bin-related variables. */
   5870 	bin_maxclass = (pagesize >> 1);
   5871 	assert(opt_quantum_2pow >= TINY_MIN_2POW);
   5872 	ntbins = opt_quantum_2pow - TINY_MIN_2POW;
   5873 	assert(ntbins <= opt_quantum_2pow);
   5874 	nqbins = (small_max >> opt_quantum_2pow);
   5875 	nsbins = pagesize_2pow - opt_small_max_2pow - 1;
   5876 
   5877 	/* Set variables according to the value of opt_quantum_2pow. */
   5878 	quantum = (1U << opt_quantum_2pow);
   5879 	quantum_mask = quantum - 1;
   5880 	if (ntbins > 0)
   5881 		small_min = (quantum >> 1) + 1;
   5882 	else
   5883 		small_min = 1;
   5884 	assert(small_min <= quantum);
   5885 
   5886 	/* Set variables according to the value of opt_chunk_2pow. */
   5887 	chunksize = (1LU << opt_chunk_2pow);
   5888 	chunksize_mask = chunksize - 1;
   5889 	chunk_npages = (chunksize >> pagesize_2pow);
   5890 	{
   5891 		size_t header_size;
   5892 
   5893 		/*
   5894 		 * Compute the header size such that it is large
   5895 		 * enough to contain the page map and enough nodes for the
   5896 		 * worst case: one node per non-header page plus one extra for
   5897 		 * situations where we briefly have one more node allocated
   5898 		 * than we will need.
   5899 		 */
   5900 		header_size = sizeof(arena_chunk_t) +
   5901 		    (sizeof(arena_chunk_map_t) * (chunk_npages - 1));
   5902 		arena_chunk_header_npages = (header_size >> pagesize_2pow) +
   5903 		    ((header_size & pagesize_mask) != 0);
   5904 	}
   5905 	arena_maxclass = chunksize - (arena_chunk_header_npages <<
   5906 	    pagesize_2pow);
   5907 
   5908 #ifdef JEMALLOC_USES_MAP_ALIGN
   5909 	/*
   5910 	 * When using MAP_ALIGN, the alignment parameter must be a power of two
   5911 	 * multiple of the system pagesize, or mmap will fail.
   5912 	 */
   5913 	assert((chunksize % pagesize) == 0);
   5914 	assert((1 << (ffs(chunksize / pagesize) - 1)) == (chunksize/pagesize));
   5915 #endif
   5916 
   5917 	UTRACE(0, 0, 0);
   5918 
   5919 #ifdef MALLOC_STATS
   5920 	memset(&stats_chunks, 0, sizeof(chunk_stats_t));
   5921 #endif
   5922 
   5923 	/* Various sanity checks that regard configuration. */
   5924 	assert(quantum >= sizeof(void *));
   5925 	assert(quantum <= pagesize);
   5926 	assert(chunksize >= pagesize);
   5927 	assert(quantum * 4 <= chunksize);
   5928 
   5929 	/* Initialize chunks data. */
   5930 	malloc_mutex_init(&huge_mtx);
   5931 	extent_tree_ad_new(&huge);
   5932 #ifdef MALLOC_STATS
   5933 	huge_nmalloc = 0;
   5934 	huge_ndalloc = 0;
   5935 	huge_allocated = 0;
   5936 #endif
   5937 
   5938 	/* Initialize base allocation data structures. */
   5939 #ifdef MALLOC_STATS
   5940 	base_mapped = 0;
   5941 #endif
   5942 	base_nodes = NULL;
   5943 	base_reserve_regs = NULL;
   5944 	malloc_mutex_init(&base_mtx);
   5945 
   5946 #ifdef MOZ_MEMORY_NARENAS_DEFAULT_ONE
   5947 	narenas = 1;
   5948 #else
   5949 	if (ncpus > 1) {
   5950 		/*
   5951 		 * For SMP systems, create four times as many arenas as there
   5952 		 * are CPUs by default.
   5953 		 */
   5954 		opt_narenas_lshift += 2;
   5955 	}
   5956 
   5957 	/* Determine how many arenas to use. */
   5958 	narenas = ncpus;
   5959 #endif
   5960 	if (opt_narenas_lshift > 0) {
   5961 		if ((narenas << opt_narenas_lshift) > narenas)
   5962 			narenas <<= opt_narenas_lshift;
   5963 		/*
   5964 		 * Make sure not to exceed the limits of what base_alloc() can
   5965 		 * handle.
   5966 		 */
   5967 		if (narenas * sizeof(arena_t *) > chunksize)
   5968 			narenas = chunksize / sizeof(arena_t *);
   5969 	} else if (opt_narenas_lshift < 0) {
   5970 		if ((narenas >> -opt_narenas_lshift) < narenas)
   5971 			narenas >>= -opt_narenas_lshift;
   5972 		/* Make sure there is at least one arena. */
   5973 		if (narenas == 0)
   5974 			narenas = 1;
   5975 	}
   5976 #ifdef MALLOC_BALANCE
   5977 	assert(narenas != 0);
   5978 	for (narenas_2pow = 0;
   5979 	     (narenas >> (narenas_2pow + 1)) != 0;
   5980 	     narenas_2pow++);
   5981 #endif
   5982 
   5983 #ifdef NO_TLS
   5984 	if (narenas > 1) {
   5985 		static const unsigned primes[] = {1, 3, 5, 7, 11, 13, 17, 19,
   5986 		    23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
   5987 		    89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
   5988 		    151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
   5989 		    223, 227, 229, 233, 239, 241, 251, 257, 263};
   5990 		unsigned nprimes, parenas;
   5991 
   5992 		/*
   5993 		 * Pick a prime number of hash arenas that is more than narenas
   5994 		 * so that direct hashing of pthread_self() pointers tends to
   5995 		 * spread allocations evenly among the arenas.
   5996 		 */
   5997 		assert((narenas & 1) == 0); /* narenas must be even. */
   5998 		nprimes = (sizeof(primes) >> SIZEOF_INT_2POW);
   5999 		parenas = primes[nprimes - 1]; /* In case not enough primes. */
   6000 		for (i = 1; i < nprimes; i++) {
   6001 			if (primes[i] > narenas) {
   6002 				parenas = primes[i];
   6003 				break;
   6004 			}
   6005 		}
   6006 		narenas = parenas;
   6007 	}
   6008 #endif
   6009 
   6010 #ifndef NO_TLS
   6011 #  ifndef MALLOC_BALANCE
   6012 	next_arena = 0;
   6013 #  endif
   6014 #endif
   6015 
   6016 	/* Allocate and initialize arenas. */
   6017 	arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas);
   6018 	if (arenas == NULL) {
   6019 #ifndef MOZ_MEMORY_WINDOWS
   6020 		malloc_mutex_unlock(&init_lock);
   6021 #endif
   6022 		return (true);
   6023 	}
   6024 	/*
   6025 	 * Zero the array.  In practice, this should always be pre-zeroed,
   6026 	 * since it was just mmap()ed, but let's be sure.
   6027 	 */
   6028 	memset(arenas, 0, sizeof(arena_t *) * narenas);
   6029 
   6030 	/*
   6031 	 * Initialize one arena here.  The rest are lazily created in
   6032 	 * choose_arena_hard().
   6033 	 */
   6034 	arenas_extend(0);
   6035 	if (arenas[0] == NULL) {
   6036 #ifndef MOZ_MEMORY_WINDOWS
   6037 		malloc_mutex_unlock(&init_lock);
   6038 #endif
   6039 		return (true);
   6040 	}
   6041 #ifndef NO_TLS
   6042 	/*
   6043 	 * Assign the initial arena to the initial thread, in order to avoid
   6044 	 * spurious creation of an extra arena if the application switches to
   6045 	 * threaded mode.
   6046 	 */
   6047 #ifdef MOZ_MEMORY_WINDOWS
   6048 	TlsSetValue(tlsIndex, arenas[0]);
   6049 #else
   6050 	arenas_map = arenas[0];
   6051 #endif
   6052 #endif
   6053 
   6054 	/*
   6055 	 * Seed here for the initial thread, since choose_arena_hard() is only
   6056 	 * called for other threads.  The seed value doesn't really matter.
   6057 	 */
   6058 #ifdef MALLOC_BALANCE
   6059 	SPRN(balance, 42);
   6060 #endif
   6061 
   6062 	malloc_spin_init(&arenas_lock);
   6063 
   6064 #ifdef MALLOC_VALIDATE
   6065 	chunk_rtree = malloc_rtree_new((SIZEOF_PTR << 3) - opt_chunk_2pow);
   6066 	if (chunk_rtree == NULL)
   6067 		return (true);
   6068 #endif
   6069 
   6070 	/*
   6071 	 * Configure and initialize the memory reserve.  This needs to happen
   6072 	 * late during initialization, since chunks are allocated.
   6073 	 */
   6074 	malloc_mutex_init(&reserve_mtx);
   6075 	reserve_min = 0;
   6076 	reserve_cur = 0;
   6077 	reserve_max = 0;
   6078 	if (RESERVE_RANGE_2POW_DEFAULT + opt_reserve_range_lshift >= 0) {
   6079 		reserve_max += chunksize << (RESERVE_RANGE_2POW_DEFAULT +
   6080 		    opt_reserve_range_lshift);
   6081 	}
   6082 	ql_new(&reserve_regs);
   6083 	reserve_seq = 0;
   6084 	extent_tree_szad_new(&reserve_chunks_szad);
   6085 	extent_tree_ad_new(&reserve_chunks_ad);
   6086 	if (RESERVE_MIN_2POW_DEFAULT + opt_reserve_min_lshift >= 0) {
   6087 		reserve_min_set(chunksize << (RESERVE_MIN_2POW_DEFAULT +
   6088 		    opt_reserve_min_lshift));
   6089 	}
   6090 
   6091 	malloc_initialized = true;
   6092 #ifndef MOZ_MEMORY_WINDOWS
   6093 	malloc_mutex_unlock(&init_lock);
   6094 #endif
   6095 	return (false);
   6096 }
   6097 
   6098 /* XXX Why not just expose malloc_print_stats()? */
   6099 #ifdef MOZ_MEMORY_WINDOWS
   6100 void
   6101 malloc_shutdown()
   6102 {
   6103 
   6104 	malloc_print_stats();
   6105 }
   6106 #endif
   6107 
   6108 /*
   6109  * End general internal functions.
   6110  */
   6111 /******************************************************************************/
   6112 /*
   6113  * Begin malloc(3)-compatible functions.
   6114  */
   6115 
   6116 /*
   6117  * Inline the standard malloc functions if they are being subsumed by Darwin's
   6118  * zone infrastructure.
   6119  */
   6120 #ifdef MOZ_MEMORY_DARWIN
   6121 #  define ZONE_INLINE	inline
   6122 #else
   6123 #  define ZONE_INLINE
   6124 #endif
   6125 
   6126 /* Mangle standard interfaces on Darwin and Windows CE,
   6127    in order to avoid linking problems. */
   6128 #if defined(MOZ_MEMORY_DARWIN)
   6129 #define	malloc(a)	moz_malloc(a)
   6130 #define	valloc(a)	moz_valloc(a)
   6131 #define	calloc(a, b)	moz_calloc(a, b)
   6132 #define	realloc(a, b)	moz_realloc(a, b)
   6133 #define	free(a)		moz_free(a)
   6134 #endif
   6135 
   6136 ZONE_INLINE
   6137 void *
   6138 malloc(size_t size)
   6139 {
   6140 	void *ret;
   6141 
   6142 	if (malloc_init()) {
   6143 		ret = NULL;
   6144 		goto RETURN;
   6145 	}
   6146 
   6147 	if (size == 0) {
   6148 #ifdef MALLOC_SYSV
   6149 		if (opt_sysv == false)
   6150 #endif
   6151 			size = 1;
   6152 #ifdef MALLOC_SYSV
   6153 		else {
   6154 			ret = NULL;
   6155 			goto RETURN;
   6156 		}
   6157 #endif
   6158 	}
   6159 
   6160 	ret = imalloc(size);
   6161 
   6162 RETURN:
   6163 	if (ret == NULL) {
   6164 #ifdef MALLOC_XMALLOC
   6165 		if (opt_xmalloc) {
   6166 			_malloc_message(_getprogname(),
   6167 			    ": (malloc) Error in malloc(): out of memory\n", "",
   6168 			    "");
   6169 			abort();
   6170 		}
   6171 #endif
   6172 		errno = ENOMEM;
   6173 	}
   6174 
   6175 	UTRACE(0, size, ret);
   6176 	return (ret);
   6177 }
   6178 
   6179 #ifdef MOZ_MEMORY_SOLARIS
   6180 #  ifdef __SUNPRO_C
   6181 void *
   6182 memalign(size_t alignment, size_t size);
   6183 #pragma no_inline(memalign)
   6184 #  elif (defined(__GNU_C__))
   6185 __attribute__((noinline))
   6186 #  endif
   6187 #else
   6188 inline
   6189 #endif
   6190 void *
   6191 memalign(size_t alignment, size_t size)
   6192 {
   6193 	void *ret;
   6194 
   6195 	assert(((alignment - 1) & alignment) == 0 && alignment >=
   6196 	    sizeof(void *));
   6197 
   6198 	if (malloc_init()) {
   6199 		ret = NULL;
   6200 		goto RETURN;
   6201 	}
   6202 
   6203 	ret = ipalloc(alignment, size);
   6204 
   6205 RETURN:
   6206 #ifdef MALLOC_XMALLOC
   6207 	if (opt_xmalloc && ret == NULL) {
   6208 		_malloc_message(_getprogname(),
   6209 		": (malloc) Error in memalign(): out of memory\n", "", "");
   6210 		abort();
   6211 	}
   6212 #endif
   6213 	UTRACE(0, size, ret);
   6214 	return (ret);
   6215 }
   6216 
   6217 ZONE_INLINE
   6218 int
   6219 posix_memalign(void **memptr, size_t alignment, size_t size)
   6220 {
   6221 	void *result;
   6222 
   6223 	/* Make sure that alignment is a large enough power of 2. */
   6224 	if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *)) {
   6225 #ifdef MALLOC_XMALLOC
   6226 		if (opt_xmalloc) {
   6227 			_malloc_message(_getprogname(),
   6228 			    ": (malloc) Error in posix_memalign(): "
   6229 			    "invalid alignment\n", "", "");
   6230 			abort();
   6231 		}
   6232 #endif
   6233 		return (EINVAL);
   6234 	}
   6235 
   6236 #ifdef MOZ_MEMORY_DARWIN
   6237 	result = moz_memalign(alignment, size);
   6238 #else
   6239 	result = memalign(alignment, size);
   6240 #endif
   6241 	if (result == NULL)
   6242 		return (ENOMEM);
   6243 
   6244 	*memptr = result;
   6245 	return (0);
   6246 }
   6247 
   6248 ZONE_INLINE
   6249 void *
   6250 valloc(size_t size)
   6251 {
   6252 #ifdef MOZ_MEMORY_DARWIN
   6253 	return (moz_memalign(pagesize, size));
   6254 #else
   6255 	return (memalign(pagesize, size));
   6256 #endif
   6257 }
   6258 
   6259 ZONE_INLINE
   6260 void *
   6261 calloc(size_t num, size_t size)
   6262 {
   6263 	void *ret;
   6264 	size_t num_size;
   6265 
   6266 	if (malloc_init()) {
   6267 		num_size = 0;
   6268 		ret = NULL;
   6269 		goto RETURN;
   6270 	}
   6271 
   6272 	num_size = num * size;
   6273 	if (num_size == 0) {
   6274 #ifdef MALLOC_SYSV
   6275 		if ((opt_sysv == false) && ((num == 0) || (size == 0)))
   6276 #endif
   6277 			num_size = 1;
   6278 #ifdef MALLOC_SYSV
   6279 		else {
   6280 			ret = NULL;
   6281 			goto RETURN;
   6282 		}
   6283 #endif
   6284 	/*
   6285 	 * Try to avoid division here.  We know that it isn't possible to
   6286 	 * overflow during multiplication if neither operand uses any of the
   6287 	 * most significant half of the bits in a size_t.
   6288 	 */
   6289 	} else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
   6290 	    && (num_size / size != num)) {
   6291 		/* size_t overflow. */
   6292 		ret = NULL;
   6293 		goto RETURN;
   6294 	}
   6295 
   6296 	ret = icalloc(num_size);
   6297 
   6298 RETURN:
   6299 	if (ret == NULL) {
   6300 #ifdef MALLOC_XMALLOC
   6301 		if (opt_xmalloc) {
   6302 			_malloc_message(_getprogname(),
   6303 			    ": (malloc) Error in calloc(): out of memory\n", "",
   6304 			    "");
   6305 			abort();
   6306 		}
   6307 #endif
   6308 		errno = ENOMEM;
   6309 	}
   6310 
   6311 	UTRACE(0, num_size, ret);
   6312 	return (ret);
   6313 }
   6314 
   6315 ZONE_INLINE
   6316 void *
   6317 realloc(void *ptr, size_t size)
   6318 {
   6319 	void *ret;
   6320 
   6321 	if (size == 0) {
   6322 #ifdef MALLOC_SYSV
   6323 		if (opt_sysv == false)
   6324 #endif
   6325 			size = 1;
   6326 #ifdef MALLOC_SYSV
   6327 		else {
   6328 			if (ptr != NULL)
   6329 				idalloc(ptr);
   6330 			ret = NULL;
   6331 			goto RETURN;
   6332 		}
   6333 #endif
   6334 	}
   6335 
   6336 	if (ptr != NULL) {
   6337 		assert(malloc_initialized);
   6338 
   6339 		ret = iralloc(ptr, size);
   6340 
   6341 		if (ret == NULL) {
   6342 #ifdef MALLOC_XMALLOC
   6343 			if (opt_xmalloc) {
   6344 				_malloc_message(_getprogname(),
   6345 				    ": (malloc) Error in realloc(): out of "
   6346 				    "memory\n", "", "");
   6347 				abort();
   6348 			}
   6349 #endif
   6350 			errno = ENOMEM;
   6351 		}
   6352 	} else {
   6353 		if (malloc_init())
   6354 			ret = NULL;
   6355 		else
   6356 			ret = imalloc(size);
   6357 
   6358 		if (ret == NULL) {
   6359 #ifdef MALLOC_XMALLOC
   6360 			if (opt_xmalloc) {
   6361 				_malloc_message(_getprogname(),
   6362 				    ": (malloc) Error in realloc(): out of "
   6363 				    "memory\n", "", "");
   6364 				abort();
   6365 			}
   6366 #endif
   6367 			errno = ENOMEM;
   6368 		}
   6369 	}
   6370 
   6371 #ifdef MALLOC_SYSV
   6372 RETURN:
   6373 #endif
   6374 	UTRACE(ptr, size, ret);
   6375 	return (ret);
   6376 }
   6377 
   6378 ZONE_INLINE
   6379 void
   6380 free(void *ptr)
   6381 {
   6382 
   6383 	UTRACE(ptr, 0, 0);
   6384 	if (ptr != NULL) {
   6385 		assert(malloc_initialized);
   6386 
   6387 		idalloc(ptr);
   6388 	}
   6389 }
   6390 
   6391 /*
   6392  * End malloc(3)-compatible functions.
   6393  */
   6394 /******************************************************************************/
   6395 /*
   6396  * Begin non-standard functions.
   6397  */
   6398 
   6399 size_t
   6400 malloc_usable_size(const void *ptr)
   6401 {
   6402 
   6403 #ifdef MALLOC_VALIDATE
   6404 	return (isalloc_validate(ptr));
   6405 #else
   6406 	assert(ptr != NULL);
   6407 
   6408 	return (isalloc(ptr));
   6409 #endif
   6410 }
   6411 
   6412 void
   6413 jemalloc_stats(jemalloc_stats_t *stats)
   6414 {
   6415 	size_t i;
   6416 
   6417 	assert(stats != NULL);
   6418 
   6419 	/*
   6420 	 * Gather runtime settings.
   6421 	 */
   6422 	stats->opt_abort = opt_abort;
   6423 	stats->opt_junk =
   6424 #ifdef MALLOC_FILL
   6425 	    opt_junk ? true :
   6426 #endif
   6427 	    false;
   6428 	stats->opt_utrace =
   6429 #ifdef MALLOC_UTRACE
   6430 	    opt_utrace ? true :
   6431 #endif
   6432 	    false;
   6433 	stats->opt_sysv =
   6434 #ifdef MALLOC_SYSV
   6435 	    opt_sysv ? true :
   6436 #endif
   6437 	    false;
   6438 	stats->opt_xmalloc =
   6439 #ifdef MALLOC_XMALLOC
   6440 	    opt_xmalloc ? true :
   6441 #endif
   6442 	    false;
   6443 	stats->opt_zero =
   6444 #ifdef MALLOC_FILL
   6445 	    opt_zero ? true :
   6446 #endif
   6447 	    false;
   6448 	stats->narenas = narenas;
   6449 	stats->balance_threshold =
   6450 #ifdef MALLOC_BALANCE
   6451 	    opt_balance_threshold
   6452 #else
   6453 	    SIZE_T_MAX
   6454 #endif
   6455 	    ;
   6456 	stats->quantum = quantum;
   6457 	stats->small_max = small_max;
   6458 	stats->large_max = arena_maxclass;
   6459 	stats->chunksize = chunksize;
   6460 	stats->dirty_max = opt_dirty_max;
   6461 
   6462 	malloc_mutex_lock(&reserve_mtx);
   6463 	stats->reserve_min = reserve_min;
   6464 	stats->reserve_max = reserve_max;
   6465 	stats->reserve_cur = reserve_cur;
   6466 	malloc_mutex_unlock(&reserve_mtx);
   6467 
   6468 	/*
   6469 	 * Gather current memory usage statistics.
   6470 	 */
   6471 	stats->mapped = 0;
   6472 	stats->committed = 0;
   6473 	stats->allocated = 0;
   6474 	stats->dirty = 0;
   6475 
   6476 	/* Get huge mapped/allocated. */
   6477 	malloc_mutex_lock(&huge_mtx);
   6478 	stats->mapped += stats_chunks.curchunks * chunksize;
   6479 #ifdef MALLOC_DECOMMIT
   6480 	stats->committed += huge_allocated;
   6481 #endif
   6482 	stats->allocated += huge_allocated;
   6483 	malloc_mutex_unlock(&huge_mtx);
   6484 
   6485 	/* Get base mapped. */
   6486 	malloc_mutex_lock(&base_mtx);
   6487 	stats->mapped += base_mapped;
   6488 #ifdef MALLOC_DECOMMIT
   6489 	stats->committed += base_mapped;
   6490 #endif
   6491 	malloc_mutex_unlock(&base_mtx);
   6492 
   6493 	/* Iterate over arenas and their chunks. */
   6494 	for (i = 0; i < narenas; i++) {
   6495 		arena_t *arena = arenas[i];
   6496 		if (arena != NULL) {
   6497 			arena_chunk_t *chunk;
   6498 
   6499 			malloc_spin_lock(&arena->lock);
   6500 			stats->allocated += arena->stats.allocated_small;
   6501 			stats->allocated += arena->stats.allocated_large;
   6502 #ifdef MALLOC_DECOMMIT
   6503 			rb_foreach_begin(arena_chunk_t, link_dirty,
   6504 			    &arena->chunks_dirty, chunk) {
   6505 				size_t j;
   6506 
   6507 				for (j = 0; j < chunk_npages; j++) {
   6508 					if ((chunk->map[j].bits &
   6509 					    CHUNK_MAP_DECOMMITTED) == 0)
   6510 						stats->committed += pagesize;
   6511 				}
   6512 			} rb_foreach_end(arena_chunk_t, link_dirty,
   6513 			    &arena->chunks_dirty, chunk)
   6514 #endif
   6515 			stats->dirty += (arena->ndirty << pagesize_2pow);
   6516 			malloc_spin_unlock(&arena->lock);
   6517 		}
   6518 	}
   6519 
   6520 #ifndef MALLOC_DECOMMIT
   6521 	stats->committed = stats->mapped;
   6522 #endif
   6523 }
   6524 
   6525 void *
   6526 xmalloc(size_t size)
   6527 {
   6528 	void *ret;
   6529 
   6530 	if (malloc_init())
   6531 		reserve_fail(size, "xmalloc");
   6532 
   6533 	if (size == 0) {
   6534 #ifdef MALLOC_SYSV
   6535 		if (opt_sysv == false)
   6536 #endif
   6537 			size = 1;
   6538 #ifdef MALLOC_SYSV
   6539 		else {
   6540 			_malloc_message(_getprogname(),
   6541 			    ": (malloc) Error in xmalloc(): ",
   6542 			    "invalid size 0", "\n");
   6543 			abort();
   6544 		}
   6545 #endif
   6546 	}
   6547 
   6548 	ret = imalloc(size);
   6549 	if (ret == NULL) {
   6550 		uint64_t seq = 0;
   6551 
   6552 		do {
   6553 			seq = reserve_crit(size, "xmalloc", seq);
   6554 			ret = imalloc(size);
   6555 		} while (ret == NULL);
   6556 	}
   6557 
   6558 	UTRACE(0, size, ret);
   6559 	return (ret);
   6560 }
   6561 
   6562 void *
   6563 xcalloc(size_t num, size_t size)
   6564 {
   6565 	void *ret;
   6566 	size_t num_size;
   6567 
   6568 	num_size = num * size;
   6569 	if (malloc_init())
   6570 		reserve_fail(num_size, "xcalloc");
   6571 
   6572 	if (num_size == 0) {
   6573 #ifdef MALLOC_SYSV
   6574 		if ((opt_sysv == false) && ((num == 0) || (size == 0)))
   6575 #endif
   6576 			num_size = 1;
   6577 #ifdef MALLOC_SYSV
   6578 		else {
   6579 			_malloc_message(_getprogname(),
   6580 			    ": (malloc) Error in xcalloc(): ",
   6581 			    "invalid size 0", "\n");
   6582 			abort();
   6583 		}
   6584 #endif
   6585 	/*
   6586 	 * Try to avoid division here.  We know that it isn't possible to
   6587 	 * overflow during multiplication if neither operand uses any of the
   6588 	 * most significant half of the bits in a size_t.
   6589 	 */
   6590 	} else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
   6591 	    && (num_size / size != num)) {
   6592 		/* size_t overflow. */
   6593 		_malloc_message(_getprogname(),
   6594 		    ": (malloc) Error in xcalloc(): ",
   6595 		    "size overflow", "\n");
   6596 		abort();
   6597 	}
   6598 
   6599 	ret = icalloc(num_size);
   6600 	if (ret == NULL) {
   6601 		uint64_t seq = 0;
   6602 
   6603 		do {
   6604 			seq = reserve_crit(num_size, "xcalloc", seq);
   6605 			ret = icalloc(num_size);
   6606 		} while (ret == NULL);
   6607 	}
   6608 
   6609 	UTRACE(0, num_size, ret);
   6610 	return (ret);
   6611 }
   6612 
   6613 void *
   6614 xrealloc(void *ptr, size_t size)
   6615 {
   6616 	void *ret;
   6617 
   6618 	if (size == 0) {
   6619 #ifdef MALLOC_SYSV
   6620 		if (opt_sysv == false)
   6621 #endif
   6622 			size = 1;
   6623 #ifdef MALLOC_SYSV
   6624 		else {
   6625 			if (ptr != NULL)
   6626 				idalloc(ptr);
   6627 			_malloc_message(_getprogname(),
   6628 			    ": (malloc) Error in xrealloc(): ",
   6629 			    "invalid size 0", "\n");
   6630 			abort();
   6631 		}
   6632 #endif
   6633 	}
   6634 
   6635 	if (ptr != NULL) {
   6636 		assert(malloc_initialized);
   6637 
   6638 		ret = iralloc(ptr, size);
   6639 		if (ret == NULL) {
   6640 			uint64_t seq = 0;
   6641 
   6642 			do {
   6643 				seq = reserve_crit(size, "xrealloc", seq);
   6644 				ret = iralloc(ptr, size);
   6645 			} while (ret == NULL);
   6646 		}
   6647 	} else {
   6648 		if (malloc_init())
   6649 			reserve_fail(size, "xrealloc");
   6650 
   6651 		ret = imalloc(size);
   6652 		if (ret == NULL) {
   6653 			uint64_t seq = 0;
   6654 
   6655 			do {
   6656 				seq = reserve_crit(size, "xrealloc", seq);
   6657 				ret = imalloc(size);
   6658 			} while (ret == NULL);
   6659 		}
   6660 	}
   6661 
   6662 	UTRACE(ptr, size, ret);
   6663 	return (ret);
   6664 }
   6665 
   6666 void *
   6667 xmemalign(size_t alignment, size_t size)
   6668 {
   6669 	void *ret;
   6670 
   6671 	assert(((alignment - 1) & alignment) == 0 && alignment >=
   6672 	    sizeof(void *));
   6673 
   6674 	if (malloc_init())
   6675 		reserve_fail(size, "xmemalign");
   6676 
   6677 	ret = ipalloc(alignment, size);
   6678 	if (ret == NULL) {
   6679 		uint64_t seq = 0;
   6680 
   6681 		do {
   6682 			seq = reserve_crit(size, "xmemalign", seq);
   6683 			ret = ipalloc(alignment, size);
   6684 		} while (ret == NULL);
   6685 	}
   6686 
   6687 	UTRACE(0, size, ret);
   6688 	return (ret);
   6689 }
   6690 
   6691 static void
   6692 reserve_shrink(void)
   6693 {
   6694 	extent_node_t *node;
   6695 
   6696 	assert(reserve_cur > reserve_max);
   6697 #ifdef MALLOC_DEBUG
   6698 	{
   6699 		extent_node_t *node;
   6700 		size_t reserve_size;
   6701 
   6702 		reserve_size = 0;
   6703 		rb_foreach_begin(extent_node_t, link_szad, &reserve_chunks_szad,
   6704 		    node) {
   6705 			reserve_size += node->size;
   6706 		} rb_foreach_end(extent_node_t, link_szad, &reserve_chunks_szad,
   6707 		    node)
   6708 		assert(reserve_size == reserve_cur);
   6709 
   6710 		reserve_size = 0;
   6711 		rb_foreach_begin(extent_node_t, link_ad, &reserve_chunks_ad,
   6712 		    node) {
   6713 			reserve_size += node->size;
   6714 		} rb_foreach_end(extent_node_t, link_ad, &reserve_chunks_ad,
   6715 		    node)
   6716 		assert(reserve_size == reserve_cur);
   6717 	}
   6718 #endif
   6719 
   6720 	/* Discard chunks until the the reserve is below the size limit. */
   6721 	rb_foreach_reverse_begin(extent_node_t, link_ad, &reserve_chunks_ad,
   6722 	    node) {
   6723 #ifndef MALLOC_DECOMMIT
   6724 		if (node->size <= reserve_cur - reserve_max) {
   6725 #endif
   6726 			extent_node_t *tnode = extent_tree_ad_prev(
   6727 			    &reserve_chunks_ad, node);
   6728 
   6729 #ifdef MALLOC_DECOMMIT
   6730 			assert(node->size <= reserve_cur - reserve_max);
   6731 #endif
   6732 
   6733 			/* Discard the entire [multi-]chunk. */
   6734 			extent_tree_szad_remove(&reserve_chunks_szad, node);
   6735 			extent_tree_ad_remove(&reserve_chunks_ad, node);
   6736 			reserve_cur -= node->size;
   6737 			pages_unmap(node->addr, node->size);
   6738 #ifdef MALLOC_STATS
   6739 			stats_chunks.curchunks -= (node->size / chunksize);
   6740 #endif
   6741 			base_node_dealloc(node);
   6742 			if (reserve_cur == reserve_max)
   6743 				break;
   6744 
   6745 			rb_foreach_reverse_prev(extent_node_t, link_ad,
   6746 			    extent_ad_comp, &reserve_chunks_ad, tnode);
   6747 #ifndef MALLOC_DECOMMIT
   6748 		} else {
   6749 			/* Discard the end of the multi-chunk. */
   6750 			extent_tree_szad_remove(&reserve_chunks_szad, node);
   6751 			node->size -= reserve_cur - reserve_max;
   6752 			extent_tree_szad_insert(&reserve_chunks_szad, node);
   6753 			pages_unmap((void *)((uintptr_t)node->addr +
   6754 			    node->size), reserve_cur - reserve_max);
   6755 #ifdef MALLOC_STATS
   6756 			stats_chunks.curchunks -= ((reserve_cur - reserve_max) /
   6757 			    chunksize);
   6758 #endif
   6759 			reserve_cur = reserve_max;
   6760 			break;
   6761 		}
   6762 #endif
   6763 		assert(reserve_cur > reserve_max);
   6764 	} rb_foreach_reverse_end(extent_node_t, link_ad, &reserve_chunks_ad,
   6765 	    node)
   6766 }
   6767 
   6768 /* Send a condition notification. */
   6769 static uint64_t
   6770 reserve_notify(reserve_cnd_t cnd, size_t size, uint64_t seq)
   6771 {
   6772 	reserve_reg_t *reg;
   6773 
   6774 	/* seq is used to keep track of distinct condition-causing events. */
   6775 	if (seq == 0) {
   6776 		/* Allocate new sequence number. */
   6777 		reserve_seq++;
   6778 		seq = reserve_seq;
   6779 	}
   6780 
   6781 	/*
   6782 	 * Advance to the next callback registration and send a notification,
   6783 	 * unless one has already been sent for this condition-causing event.
   6784 	 */
   6785 	reg = ql_first(&reserve_regs);
   6786 	if (reg == NULL)
   6787 		return (0);
   6788 	ql_first(&reserve_regs) = ql_next(&reserve_regs, reg, link);
   6789 	if (reg->seq == seq)
   6790 		return (0);
   6791 	reg->seq = seq;
   6792 	malloc_mutex_unlock(&reserve_mtx);
   6793 	reg->cb(reg->ctx, cnd, size);
   6794 	malloc_mutex_lock(&reserve_mtx);
   6795 
   6796 	return (seq);
   6797 }
   6798 
   6799 /* Allocation failure due to OOM.  Try to free some memory via callbacks. */
   6800 static uint64_t
   6801 reserve_crit(size_t size, const char *fname, uint64_t seq)
   6802 {
   6803 
   6804 	/*
   6805 	 * Send one condition notification.  Iteration is handled by the
   6806 	 * caller of this function.
   6807 	 */
   6808 	malloc_mutex_lock(&reserve_mtx);
   6809 	seq = reserve_notify(RESERVE_CND_CRIT, size, seq);
   6810 	malloc_mutex_unlock(&reserve_mtx);
   6811 
   6812 	/* If no notification could be sent, then no further recourse exists. */
   6813 	if (seq == 0)
   6814 		reserve_fail(size, fname);
   6815 
   6816 	return (seq);
   6817 }
   6818 
   6819 /* Permanent allocation failure due to OOM. */
   6820 static void
   6821 reserve_fail(size_t size, const char *fname)
   6822 {
   6823 	uint64_t seq = 0;
   6824 
   6825 	/* Send fail notifications. */
   6826 	malloc_mutex_lock(&reserve_mtx);
   6827 	do {
   6828 		seq = reserve_notify(RESERVE_CND_FAIL, size, seq);
   6829 	} while (seq != 0);
   6830 	malloc_mutex_unlock(&reserve_mtx);
   6831 
   6832 	/* Terminate the application. */
   6833 	_malloc_message(_getprogname(),
   6834 	    ": (malloc) Error in ", fname, "(): out of memory\n");
   6835 	abort();
   6836 }
   6837 
   6838 bool
   6839 reserve_cb_register(reserve_cb_t *cb, void *ctx)
   6840 {
   6841 	reserve_reg_t *reg = base_reserve_reg_alloc();
   6842 	if (reg == NULL)
   6843 		return (true);
   6844 
   6845 	ql_elm_new(reg, link);
   6846 	reg->cb = cb;
   6847 	reg->ctx = ctx;
   6848 	reg->seq = 0;
   6849 
   6850 	malloc_mutex_lock(&reserve_mtx);
   6851 	ql_head_insert(&reserve_regs, reg, link);
   6852 	malloc_mutex_unlock(&reserve_mtx);
   6853 
   6854 	return (false);
   6855 }
   6856 
   6857 bool
   6858 reserve_cb_unregister(reserve_cb_t *cb, void *ctx)
   6859 {
   6860 	reserve_reg_t *reg = NULL;
   6861 
   6862 	malloc_mutex_lock(&reserve_mtx);
   6863 	ql_foreach(reg, &reserve_regs, link) {
   6864 		if (reg->cb == cb && reg->ctx == ctx) {
   6865 			ql_remove(&reserve_regs, reg, link);
   6866 			break;
   6867 		}
   6868 	}
   6869 	malloc_mutex_unlock(&reserve_mtx);
   6870 
   6871 	if (reg != NULL)
   6872 		base_reserve_reg_dealloc(reg);
   6873 		return (false);
   6874 	return (true);
   6875 }
   6876 
   6877 size_t
   6878 reserve_cur_get(void)
   6879 {
   6880 	size_t ret;
   6881 
   6882 	malloc_mutex_lock(&reserve_mtx);
   6883 	ret = reserve_cur;
   6884 	malloc_mutex_unlock(&reserve_mtx);
   6885 
   6886 	return (ret);
   6887 }
   6888 
   6889 size_t
   6890 reserve_min_get(void)
   6891 {
   6892 	size_t ret;
   6893 
   6894 	malloc_mutex_lock(&reserve_mtx);
   6895 	ret = reserve_min;
   6896 	malloc_mutex_unlock(&reserve_mtx);
   6897 
   6898 	return (ret);
   6899 }
   6900 
   6901 bool
   6902 reserve_min_set(size_t min)
   6903 {
   6904 
   6905 	min = CHUNK_CEILING(min);
   6906 
   6907 	malloc_mutex_lock(&reserve_mtx);
   6908 	/* Keep |reserve_max - reserve_min| the same. */
   6909 	if (min < reserve_min) {
   6910 		reserve_max -= reserve_min - min;
   6911 		reserve_min = min;
   6912 	} else {
   6913 		/* Protect against wrap-around. */
   6914 		if (reserve_max + min - reserve_min < reserve_max) {
   6915 			reserve_min = SIZE_T_MAX - (reserve_max - reserve_min)
   6916 			    - chunksize + 1;
   6917 			reserve_max = SIZE_T_MAX - chunksize + 1;
   6918 		} else {
   6919 			reserve_max += min - reserve_min;
   6920 			reserve_min = min;
   6921 		}
   6922 	}
   6923 
   6924 	/* Resize the reserve if necessary. */
   6925 	if (reserve_cur < reserve_min) {
   6926 		size_t size = reserve_min - reserve_cur;
   6927 
   6928 		/* Force the reserve to grow by allocating/deallocating. */
   6929 		malloc_mutex_unlock(&reserve_mtx);
   6930 #ifdef MALLOC_DECOMMIT
   6931 		{
   6932 			void **chunks;
   6933 			size_t i, n;
   6934 
   6935 			n = size >> opt_chunk_2pow;
   6936 			chunks = (void**)imalloc(n * sizeof(void *));
   6937 			if (chunks == NULL)
   6938 				return (true);
   6939 			for (i = 0; i < n; i++) {
   6940 				chunks[i] = huge_malloc(chunksize, false);
   6941 				if (chunks[i] == NULL) {
   6942 					size_t j;
   6943 
   6944 					for (j = 0; j < i; j++) {
   6945 						huge_dalloc(chunks[j]);
   6946 					}
   6947 					idalloc(chunks);
   6948 					return (true);
   6949 				}
   6950 			}
   6951 			for (i = 0; i < n; i++)
   6952 				huge_dalloc(chunks[i]);
   6953 			idalloc(chunks);
   6954 		}
   6955 #else
   6956 		{
   6957 			void *x = huge_malloc(size, false);
   6958 			if (x == NULL) {
   6959 				return (true);
   6960 			}
   6961 			huge_dalloc(x);
   6962 		}
   6963 #endif
   6964 	} else if (reserve_cur > reserve_max) {
   6965 		reserve_shrink();
   6966 		malloc_mutex_unlock(&reserve_mtx);
   6967 	} else
   6968 		malloc_mutex_unlock(&reserve_mtx);
   6969 
   6970 	return (false);
   6971 }
   6972 
   6973 #ifdef MOZ_MEMORY_WINDOWS
   6974 void*
   6975 _recalloc(void *ptr, size_t count, size_t size)
   6976 {
   6977 	size_t oldsize = (ptr != NULL) ? isalloc(ptr) : 0;
   6978 	size_t newsize = count * size;
   6979 
   6980 	/*
   6981 	 * In order for all trailing bytes to be zeroed, the caller needs to
   6982 	 * use calloc(), followed by recalloc().  However, the current calloc()
   6983 	 * implementation only zeros the bytes requested, so if recalloc() is
   6984 	 * to work 100% correctly, calloc() will need to change to zero
   6985 	 * trailing bytes.
   6986 	 */
   6987 
   6988 	ptr = realloc(ptr, newsize);
   6989 	if (ptr != NULL && oldsize < newsize) {
   6990 		memset((void *)((uintptr_t)ptr + oldsize), 0, newsize -
   6991 		    oldsize);
   6992 	}
   6993 
   6994 	return ptr;
   6995 }
   6996 
   6997 /*
   6998  * This impl of _expand doesn't ever actually expand or shrink blocks: it
   6999  * simply replies that you may continue using a shrunk block.
   7000  */
   7001 void*
   7002 _expand(void *ptr, size_t newsize)
   7003 {
   7004 	if (isalloc(ptr) >= newsize)
   7005 		return ptr;
   7006 
   7007 	return NULL;
   7008 }
   7009 
   7010 size_t
   7011 _msize(const void *ptr)
   7012 {
   7013 
   7014 	return malloc_usable_size(ptr);
   7015 }
   7016 #endif
   7017 
   7018 /*
   7019  * End non-standard functions.
   7020  */
   7021 /******************************************************************************/
   7022 /*
   7023  * Begin library-private functions, used by threading libraries for protection
   7024  * of malloc during fork().  These functions are only called if the program is
   7025  * running in threaded mode, so there is no need to check whether the program
   7026  * is threaded here.
   7027  */
   7028 
   7029 void
   7030 _malloc_prefork(void)
   7031 {
   7032 	unsigned i;
   7033 
   7034 	/* Acquire all mutexes in a safe order. */
   7035 
   7036 	malloc_spin_lock(&arenas_lock);
   7037 	for (i = 0; i < narenas; i++) {
   7038 		if (arenas[i] != NULL)
   7039 			malloc_spin_lock(&arenas[i]->lock);
   7040 	}
   7041 	malloc_spin_unlock(&arenas_lock);
   7042 
   7043 	malloc_mutex_lock(&base_mtx);
   7044 
   7045 	malloc_mutex_lock(&huge_mtx);
   7046 }
   7047 
   7048 void
   7049 _malloc_postfork(void)
   7050 {
   7051 	unsigned i;
   7052 
   7053 	/* Release all mutexes, now that fork() has completed. */
   7054 
   7055 	malloc_mutex_unlock(&huge_mtx);
   7056 
   7057 	malloc_mutex_unlock(&base_mtx);
   7058 
   7059 	malloc_spin_lock(&arenas_lock);
   7060 	for (i = 0; i < narenas; i++) {
   7061 		if (arenas[i] != NULL)
   7062 			malloc_spin_unlock(&arenas[i]->lock);
   7063 	}
   7064 	malloc_spin_unlock(&arenas_lock);
   7065 }
   7066 
   7067 /*
   7068  * End library-private functions.
   7069  */
   7070 /******************************************************************************/
   7071 
   7072 #ifdef HAVE_LIBDL
   7073 #  include <dlfcn.h>
   7074 #endif
   7075 
   7076 #ifdef MOZ_MEMORY_DARWIN
   7077 static malloc_zone_t zone;
   7078 static struct malloc_introspection_t zone_introspect;
   7079 
   7080 static size_t
   7081 zone_size(malloc_zone_t *zone, void *ptr)
   7082 {
   7083 
   7084 	/*
   7085 	 * There appear to be places within Darwin (such as setenv(3)) that
   7086 	 * cause calls to this function with pointers that *no* zone owns.  If
   7087 	 * we knew that all pointers were owned by *some* zone, we could split
   7088 	 * our zone into two parts, and use one as the default allocator and
   7089 	 * the other as the default deallocator/reallocator.  Since that will
   7090 	 * not work in practice, we must check all pointers to assure that they
   7091 	 * reside within a mapped chunk before determining size.
   7092 	 */
   7093 	return (isalloc_validate(ptr));
   7094 }
   7095 
   7096 static void *
   7097 zone_malloc(malloc_zone_t *zone, size_t size)
   7098 {
   7099 
   7100 	return (malloc(size));
   7101 }
   7102 
   7103 static void *
   7104 zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
   7105 {
   7106 
   7107 	return (calloc(num, size));
   7108 }
   7109 
   7110 static void *
   7111 zone_valloc(malloc_zone_t *zone, size_t size)
   7112 {
   7113 	void *ret = NULL; /* Assignment avoids useless compiler warning. */
   7114 
   7115 	posix_memalign(&ret, pagesize, size);
   7116 
   7117 	return (ret);
   7118 }
   7119 
   7120 static void
   7121 zone_free(malloc_zone_t *zone, void *ptr)
   7122 {
   7123 
   7124 	free(ptr);
   7125 }
   7126 
   7127 static void *
   7128 zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
   7129 {
   7130 
   7131 	return (realloc(ptr, size));
   7132 }
   7133 
   7134 static void *
   7135 zone_destroy(malloc_zone_t *zone)
   7136 {
   7137 
   7138 	/* This function should never be called. */
   7139 	assert(false);
   7140 	return (NULL);
   7141 }
   7142 
   7143 static size_t
   7144 zone_good_size(malloc_zone_t *zone, size_t size)
   7145 {
   7146 	size_t ret;
   7147 	void *p;
   7148 
   7149 	/*
   7150 	 * Actually create an object of the appropriate size, then find out
   7151 	 * how large it could have been without moving up to the next size
   7152 	 * class.
   7153 	 */
   7154 	p = malloc(size);
   7155 	if (p != NULL) {
   7156 		ret = isalloc(p);
   7157 		free(p);
   7158 	} else
   7159 		ret = size;
   7160 
   7161 	return (ret);
   7162 }
   7163 
   7164 static void
   7165 zone_force_lock(malloc_zone_t *zone)
   7166 {
   7167 
   7168 	_malloc_prefork();
   7169 }
   7170 
   7171 static void
   7172 zone_force_unlock(malloc_zone_t *zone)
   7173 {
   7174 
   7175 	_malloc_postfork();
   7176 }
   7177 
   7178 static malloc_zone_t *
   7179 create_zone(void)
   7180 {
   7181 
   7182 	assert(malloc_initialized);
   7183 
   7184 	zone.size = (void *)zone_size;
   7185 	zone.malloc = (void *)zone_malloc;
   7186 	zone.calloc = (void *)zone_calloc;
   7187 	zone.valloc = (void *)zone_valloc;
   7188 	zone.free = (void *)zone_free;
   7189 	zone.realloc = (void *)zone_realloc;
   7190 	zone.destroy = (void *)zone_destroy;
   7191 	zone.zone_name = "jemalloc_zone";
   7192 	zone.batch_malloc = NULL;
   7193 	zone.batch_free = NULL;
   7194 	zone.introspect = &zone_introspect;
   7195 
   7196 	zone_introspect.enumerator = NULL;
   7197 	zone_introspect.good_size = (void *)zone_good_size;
   7198 	zone_introspect.check = NULL;
   7199 	zone_introspect.print = NULL;
   7200 	zone_introspect.log = NULL;
   7201 	zone_introspect.force_lock = (void *)zone_force_lock;
   7202 	zone_introspect.force_unlock = (void *)zone_force_unlock;
   7203 	zone_introspect.statistics = NULL;
   7204 
   7205 	return (&zone);
   7206 }
   7207 
   7208 __attribute__((constructor))
   7209 void
   7210 jemalloc_darwin_init(void)
   7211 {
   7212 	extern unsigned malloc_num_zones;
   7213 	extern malloc_zone_t **malloc_zones;
   7214 
   7215 	if (malloc_init_hard())
   7216 		abort();
   7217 
   7218 	/*
   7219 	 * The following code is *not* thread-safe, so it's critical that
   7220 	 * initialization be manually triggered.
   7221 	 */
   7222 
   7223 	/* Register the custom zones. */
   7224 	malloc_zone_register(create_zone());
   7225 	assert(malloc_zones[malloc_num_zones - 1] == &zone);
   7226 
   7227 	/*
   7228 	 * Shift malloc_zones around so that zone is first, which makes it the
   7229 	 * default zone.
   7230 	 */
   7231 	assert(malloc_num_zones > 1);
   7232 	memmove(&malloc_zones[1], &malloc_zones[0],
   7233 		sizeof(malloc_zone_t *) * (malloc_num_zones - 1));
   7234 	malloc_zones[0] = &zone;
   7235 }
   7236 
   7237 #elif defined(__GLIBC__) && !defined(__UCLIBC__)
   7238 /*
   7239  * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
   7240  * to inconsistently reference libc's malloc(3)-compatible functions
   7241  * (bug 493541).
   7242  *
   7243  * These definitions interpose hooks in glibc.  The functions are actually
   7244  * passed an extra argument for the caller return address, which will be
   7245  * ignored.
   7246  */
   7247 void (*__free_hook)(void *ptr) = free;
   7248 void *(*__malloc_hook)(size_t size) = malloc;
   7249 void *(*__realloc_hook)(void *ptr, size_t size) = realloc;
   7250 void *(*__memalign_hook)(size_t alignment, size_t size) = memalign;
   7251 
   7252 #elif defined(RTLD_DEEPBIND)
   7253 /*
   7254  * XXX On systems that support RTLD_GROUP or DF_1_GROUP, do their
   7255  * implementations permit similar inconsistencies?  Should STV_SINGLETON
   7256  * visibility be used for interposition where available?
   7257  */
   7258 #  error "Interposing malloc is unsafe on this system without libc malloc hooks."
   7259 #endif
   7260