memory/mozjemalloc/jemalloc.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: t -*- */
     2 /* vim:set softtabstop=8 shiftwidth=8 noet: */
     3 /*-
     4  * Copyright (C) 2006-2008 Jason Evans <jasone@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  * NOTE: Due to Mozilla bug 691003, we cannot reserve less than one word for an
    86  * allocation on Linux or Mac.  So on 32-bit *nix, the smallest bucket size is
    87  * 4 bytes, and on 64-bit, the smallest bucket size is 8 bytes.
    88  *
    89  * A different mechanism is used for each category:
    90  *
    91  *   Small : Each size class is segregated into its own set of runs.  Each run
    92  *           maintains a bitmap of which regions are free/allocated.
    93  *
    94  *   Large : Each allocation is backed by a dedicated run.  Metadata are stored
    95  *           in the associated arena chunk header maps.
    96  *
    97  *   Huge : Each allocation is backed by a dedicated contiguous set of chunks.
    98  *          Metadata are stored in a separate red-black tree.
    99  *
   100  *******************************************************************************
   101  */
   103 #ifdef MOZ_MEMORY_ANDROID
   104 #define NO_TLS
   105 #define _pthread_self() pthread_self()
   106 #endif
   108 /*
   109  * On Linux, we use madvise(MADV_DONTNEED) to release memory back to the
   110  * operating system.  If we release 1MB of live pages with MADV_DONTNEED, our
   111  * RSS will decrease by 1MB (almost) immediately.
   112  *
   113  * On Mac, we use madvise(MADV_FREE).  Unlike MADV_DONTNEED on Linux, MADV_FREE
   114  * on Mac doesn't cause the OS to release the specified pages immediately; the
   115  * OS keeps them in our process until the machine comes under memory pressure.
   116  *
   117  * It's therefore difficult to measure the process's RSS on Mac, since, in the
   118  * absence of memory pressure, the contribution from the heap to RSS will not
   119  * decrease due to our madvise calls.
   120  *
   121  * We therefore define MALLOC_DOUBLE_PURGE on Mac.  This causes jemalloc to
   122  * track which pages have been MADV_FREE'd.  You can then call
   123  * jemalloc_purge_freed_pages(), which will force the OS to release those
   124  * MADV_FREE'd pages, making the process's RSS reflect its true memory usage.
   125  *
   126  * The jemalloc_purge_freed_pages definition in memory/build/mozmemory.h needs
   127  * to be adjusted if MALLOC_DOUBLE_PURGE is ever enabled on Linux.
   128  */
   129 #ifdef MOZ_MEMORY_DARWIN
   130 #define MALLOC_DOUBLE_PURGE
   131 #endif
   133 /*
   134  * MALLOC_PRODUCTION disables assertions and statistics gathering.  It also
   135  * defaults the A and J runtime options to off.  These settings are appropriate
   136  * for production systems.
   137  */
   138 #ifndef MOZ_MEMORY_DEBUG
   139 #  define	MALLOC_PRODUCTION
   140 #endif
   142 /*
   143  * Use only one arena by default.  Mozilla does not currently make extensive
   144  * use of concurrent allocation, so the increased fragmentation associated with
   145  * multiple arenas is not warranted.
   146  */
   147 #define	MOZ_MEMORY_NARENAS_DEFAULT_ONE
   149 /*
   150  * Pass this set of options to jemalloc as its default. It does not override
   151  * the options passed via the MALLOC_OPTIONS environment variable but is
   152  * applied in addition to them.
   153  */
   154 #ifdef MOZ_B2G
   155     /* Reduce the amount of unused dirty pages to 1MiB on B2G */
   156 #   define MOZ_MALLOC_OPTIONS "ff"
   157 #else
   158 #   define MOZ_MALLOC_OPTIONS ""
   159 #endif
   161 /*
   162  * MALLOC_STATS enables statistics calculation, and is required for
   163  * jemalloc_stats().
   164  */
   165 #define MALLOC_STATS
   167 /* Memory filling (junk/poison/zero). */
   168 #define MALLOC_FILL
   170 #ifndef MALLOC_PRODUCTION
   171    /*
   172     * MALLOC_DEBUG enables assertions and other sanity checks, and disables
   173     * inline functions.
   174     */
   175 #  define MALLOC_DEBUG
   177    /* Allocation tracing. */
   178 #  ifndef MOZ_MEMORY_WINDOWS
   179 #    define MALLOC_UTRACE
   180 #  endif
   182    /* Support optional abort() on OOM. */
   183 #  define MALLOC_XMALLOC
   185    /* Support SYSV semantics. */
   186 #  define MALLOC_SYSV
   187 #endif
   189 /*
   190  * MALLOC_VALIDATE causes malloc_usable_size() to perform some pointer
   191  * validation.  There are many possible errors that validation does not even
   192  * attempt to detect.
   193  */
   194 #define MALLOC_VALIDATE
   196 /* Embed no-op macros that support memory allocation tracking via valgrind. */
   197 #ifdef MOZ_VALGRIND
   198 #  define MALLOC_VALGRIND
   199 #endif
   200 #ifdef MALLOC_VALGRIND
   201 #  include <valgrind/valgrind.h>
   202 #else
   203 #  define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed)
   204 #  define VALGRIND_FREELIKE_BLOCK(addr, rzB)
   205 #endif
   207 /*
   208  * MALLOC_BALANCE enables monitoring of arena lock contention and dynamically
   209  * re-balances arena load if exponentially averaged contention exceeds a
   210  * certain threshold.
   211  */
   212 /* #define	MALLOC_BALANCE */
   214 /*
   215  * MALLOC_PAGEFILE causes all mmap()ed memory to be backed by temporary
   216  * files, so that if a chunk is mapped, it is guaranteed to be swappable.
   217  * This avoids asynchronous OOM failures that are due to VM over-commit.
   218  */
   219 /* #define MALLOC_PAGEFILE */
   221 #ifdef MALLOC_PAGEFILE
   222 /* Write size when initializing a page file. */
   223 #  define MALLOC_PAGEFILE_WRITE_SIZE 512
   224 #endif
   226 #if defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
   227 #define	_GNU_SOURCE /* For mremap(2). */
   228 #define	issetugid() 0
   229 #if 0 /* Enable in order to test decommit code on Linux. */
   230 #  define MALLOC_DECOMMIT
   231 #endif
   232 #endif
   234 #include <sys/types.h>
   236 #include <errno.h>
   237 #include <stdlib.h>
   238 #include <limits.h>
   239 #include <stdarg.h>
   240 #include <stdio.h>
   241 #include <string.h>
   243 #ifdef MOZ_MEMORY_WINDOWS
   245 /* Some defines from the CRT internal headers that we need here. */
   246 #define _CRT_SPINCOUNT 5000
   247 #define __crtInitCritSecAndSpinCount InitializeCriticalSectionAndSpinCount
   248 #include <io.h>
   249 #include <windows.h>
   251 #pragma warning( disable: 4267 4996 4146 )
   253 #define	bool BOOL
   254 #define	false FALSE
   255 #define	true TRUE
   256 #define	inline __inline
   257 #define	SIZE_T_MAX SIZE_MAX
   258 #define	STDERR_FILENO 2
   259 #define	PATH_MAX MAX_PATH
   260 #define	vsnprintf _vsnprintf
   262 #ifndef NO_TLS
   263 static unsigned long tlsIndex = 0xffffffff;
   264 #endif 
   266 #define	__thread
   267 #define	_pthread_self() __threadid()
   268 #define	issetugid() 0
   270 /* use MSVC intrinsics */
   271 #pragma intrinsic(_BitScanForward)
   272 static __forceinline int
   273 ffs(int x)
   274 {
   275 	unsigned long i;
   277 	if (_BitScanForward(&i, x) != 0)
   278 		return (i + 1);
   280 	return (0);
   281 }
   283 /* Implement getenv without using malloc */
   284 static char mozillaMallocOptionsBuf[64];
   286 #define	getenv xgetenv
   287 static char *
   288 getenv(const char *name)
   289 {
   291 	if (GetEnvironmentVariableA(name, (LPSTR)&mozillaMallocOptionsBuf,
   292 		    sizeof(mozillaMallocOptionsBuf)) > 0)
   293 		return (mozillaMallocOptionsBuf);
   295 	return (NULL);
   296 }
   298 typedef unsigned char uint8_t;
   299 typedef unsigned uint32_t;
   300 typedef unsigned long long uint64_t;
   301 typedef unsigned long long uintmax_t;
   302 #if defined(_WIN64)
   303 typedef long long ssize_t;
   304 #else
   305 typedef long ssize_t;
   306 #endif
   308 #define	MALLOC_DECOMMIT
   309 #endif
   311 #ifndef MOZ_MEMORY_WINDOWS
   312 #ifndef MOZ_MEMORY_SOLARIS
   313 #include <sys/cdefs.h>
   314 #endif
   315 #ifndef __DECONST
   316 #  define __DECONST(type, var)	((type)(uintptr_t)(const void *)(var))
   317 #endif
   318 #ifndef MOZ_MEMORY
   319 __FBSDID("$FreeBSD: head/lib/libc/stdlib/malloc.c 180599 2008-07-18 19:35:44Z jasone $");
   320 #include "libc_private.h"
   321 #ifdef MALLOC_DEBUG
   322 #  define _LOCK_DEBUG
   323 #endif
   324 #include "spinlock.h"
   325 #include "namespace.h"
   326 #endif
   327 #include <sys/mman.h>
   328 #ifndef MADV_FREE
   329 #  define MADV_FREE	MADV_DONTNEED
   330 #endif
   331 #ifndef MAP_NOSYNC
   332 #  define MAP_NOSYNC	0
   333 #endif
   334 #include <sys/param.h>
   335 #ifndef MOZ_MEMORY
   336 #include <sys/stddef.h>
   337 #endif
   338 #include <sys/time.h>
   339 #include <sys/types.h>
   340 #if !defined(MOZ_MEMORY_SOLARIS) && !defined(MOZ_MEMORY_ANDROID)
   341 #include <sys/sysctl.h>
   342 #endif
   343 #include <sys/uio.h>
   344 #ifndef MOZ_MEMORY
   345 #include <sys/ktrace.h> /* Must come after several other sys/ includes. */
   347 #include <machine/atomic.h>
   348 #include <machine/cpufunc.h>
   349 #include <machine/vmparam.h>
   350 #endif
   352 #include <errno.h>
   353 #include <limits.h>
   354 #ifndef SIZE_T_MAX
   355 #  define SIZE_T_MAX	SIZE_MAX
   356 #endif
   357 #include <pthread.h>
   358 #ifdef MOZ_MEMORY_DARWIN
   359 #define _pthread_self pthread_self
   360 #define _pthread_mutex_init pthread_mutex_init
   361 #define _pthread_mutex_trylock pthread_mutex_trylock
   362 #define _pthread_mutex_lock pthread_mutex_lock
   363 #define _pthread_mutex_unlock pthread_mutex_unlock
   364 #endif
   365 #include <sched.h>
   366 #include <stdarg.h>
   367 #include <stdio.h>
   368 #include <stdbool.h>
   369 #include <stdint.h>
   370 #include <stdlib.h>
   371 #include <string.h>
   372 #ifndef MOZ_MEMORY_DARWIN
   373 #include <strings.h>
   374 #endif
   375 #include <unistd.h>
   377 #ifdef MOZ_MEMORY_DARWIN
   378 #include <libkern/OSAtomic.h>
   379 #include <mach/mach_error.h>
   380 #include <mach/mach_init.h>
   381 #include <mach/vm_map.h>
   382 #include <malloc/malloc.h>
   383 #endif
   385 #ifndef MOZ_MEMORY
   386 #include "un-namespace.h"
   387 #endif
   389 #endif
   391 #include "jemalloc_types.h"
   392 #include "linkedlist.h"
   393 #include "mozmemory_wrap.h"
   395 /* Some tools, such as /dev/dsp wrappers, LD_PRELOAD libraries that
   396  * happen to override mmap() and call dlsym() from their overridden
   397  * mmap(). The problem is that dlsym() calls malloc(), and this ends
   398  * up in a dead lock in jemalloc.
   399  * On these systems, we prefer to directly use the system call.
   400  * We do that for Linux systems and kfreebsd with GNU userland.
   401  * Note sanity checks are not done (alignment of offset, ...) because
   402  * the uses of mmap are pretty limited, in jemalloc.
   403  *
   404  * On Alpha, glibc has a bug that prevents syscall() to work for system
   405  * calls with 6 arguments
   406  */
   407 #if (defined(MOZ_MEMORY_LINUX) && !defined(__alpha__)) || \
   408     (defined(MOZ_MEMORY_BSD) && defined(__GLIBC__))
   409 #include <sys/syscall.h>
   410 #if defined(SYS_mmap) || defined(SYS_mmap2)
   411 static inline
   412 void *_mmap(void *addr, size_t length, int prot, int flags,
   413             int fd, off_t offset)
   414 {
   415 /* S390 only passes one argument to the mmap system call, which is a
   416  * pointer to a structure containing the arguments */
   417 #ifdef __s390__
   418 	struct {
   419 		void *addr;
   420 		size_t length;
   421 		long prot;
   422 		long flags;
   423 		long fd;
   424 		off_t offset;
   425 	} args = { addr, length, prot, flags, fd, offset };
   426 	return (void *) syscall(SYS_mmap, &args);
   427 #else
   428 #ifdef SYS_mmap2
   429 	return (void *) syscall(SYS_mmap2, addr, length, prot, flags,
   430 	                       fd, offset >> 12);
   431 #else
   432 	return (void *) syscall(SYS_mmap, addr, length, prot, flags,
   433                                fd, offset);
   434 #endif
   435 #endif
   436 }
   437 #define mmap _mmap
   438 #define munmap(a, l) syscall(SYS_munmap, a, l)
   439 #endif
   440 #endif
   442 #ifdef MOZ_MEMORY_DARWIN
   443 static const bool isthreaded = true;
   444 #endif
   446 #if defined(MOZ_MEMORY_SOLARIS) && defined(MAP_ALIGN) && !defined(JEMALLOC_NEVER_USES_MAP_ALIGN)
   447 #define JEMALLOC_USES_MAP_ALIGN	 /* Required on Solaris 10. Might improve performance elsewhere. */
   448 #endif
   450 #define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
   452 #ifdef MOZ_MEMORY_WINDOWS
   453    /* MSVC++ does not support C99 variable-length arrays. */
   454 #  define RB_NO_C99_VARARRAYS
   455 #endif
   456 #include "rb.h"
   458 #ifdef MALLOC_DEBUG
   459    /* Disable inlining to make debugging easier. */
   460 #ifdef inline
   461 #undef inline
   462 #endif
   464 #  define inline
   465 #endif
   467 /* Size of stack-allocated buffer passed to strerror_r(). */
   468 #define	STRERROR_BUF		64
   470 /* Minimum alignment of non-tiny allocations is 2^QUANTUM_2POW_MIN bytes. */
   471 #  define QUANTUM_2POW_MIN      4
   472 #if defined(_WIN64) || defined(__LP64__)
   473 #  define SIZEOF_PTR_2POW       3
   474 #else
   475 #  define SIZEOF_PTR_2POW       2
   476 #endif
   477 #define PIC
   478 #ifndef MOZ_MEMORY_DARWIN
   479 static const bool isthreaded = true;
   480 #else
   481 #  define NO_TLS
   482 #endif
   483 #if 0
   484 #ifdef __i386__
   485 #  define QUANTUM_2POW_MIN	4
   486 #  define SIZEOF_PTR_2POW	2
   487 #  define CPU_SPINWAIT		__asm__ volatile("pause")
   488 #endif
   489 #ifdef __ia64__
   490 #  define QUANTUM_2POW_MIN	4
   491 #  define SIZEOF_PTR_2POW	3
   492 #endif
   493 #ifdef __alpha__
   494 #  define QUANTUM_2POW_MIN	4
   495 #  define SIZEOF_PTR_2POW	3
   496 #  define NO_TLS
   497 #endif
   498 #ifdef __sparc64__
   499 #  define QUANTUM_2POW_MIN	4
   500 #  define SIZEOF_PTR_2POW	3
   501 #  define NO_TLS
   502 #endif
   503 #ifdef __amd64__
   504 #  define QUANTUM_2POW_MIN	4
   505 #  define SIZEOF_PTR_2POW	3
   506 #  define CPU_SPINWAIT		__asm__ volatile("pause")
   507 #endif
   508 #ifdef __arm__
   509 #  define QUANTUM_2POW_MIN	3
   510 #  define SIZEOF_PTR_2POW	2
   511 #  define NO_TLS
   512 #endif
   513 #ifdef __mips__
   514 #  define QUANTUM_2POW_MIN	3
   515 #  define SIZEOF_PTR_2POW	2
   516 #  define NO_TLS
   517 #endif
   518 #ifdef __powerpc__
   519 #  define QUANTUM_2POW_MIN	4
   520 #  define SIZEOF_PTR_2POW	2
   521 #endif
   522 #endif
   524 #define	SIZEOF_PTR		(1U << SIZEOF_PTR_2POW)
   526 /* sizeof(int) == (1U << SIZEOF_INT_2POW). */
   527 #ifndef SIZEOF_INT_2POW
   528 #  define SIZEOF_INT_2POW	2
   529 #endif
   531 /* We can't use TLS in non-PIC programs, since TLS relies on loader magic. */
   532 #if (!defined(PIC) && !defined(NO_TLS))
   533 #  define NO_TLS
   534 #endif
   536 #ifdef NO_TLS
   537    /* MALLOC_BALANCE requires TLS. */
   538 #  ifdef MALLOC_BALANCE
   539 #    undef MALLOC_BALANCE
   540 #  endif
   541 #endif
   543 /*
   544  * Size and alignment of memory chunks that are allocated by the OS's virtual
   545  * memory system.
   546  */
   547 #define	CHUNK_2POW_DEFAULT	20
   548 /* Maximum number of dirty pages per arena. */
   549 #define	DIRTY_MAX_DEFAULT	(1U << 10)
   551 /*
   552  * Maximum size of L1 cache line.  This is used to avoid cache line aliasing,
   553  * so over-estimates are okay (up to a point), but under-estimates will
   554  * negatively affect performance.
   555  */
   556 #define	CACHELINE_2POW		6
   557 #define	CACHELINE		((size_t)(1U << CACHELINE_2POW))
   559 /*
   560  * Smallest size class to support.  On Linux and Mac, even malloc(1) must
   561  * reserve a word's worth of memory (see Mozilla bug 691003).
   562  */
   563 #ifdef MOZ_MEMORY_WINDOWS
   564 #define	TINY_MIN_2POW		1
   565 #else
   566 #define TINY_MIN_2POW           (sizeof(void*) == 8 ? 3 : 2)
   567 #endif
   569 /*
   570  * Maximum size class that is a multiple of the quantum, but not (necessarily)
   571  * a power of 2.  Above this size, allocations are rounded up to the nearest
   572  * power of 2.
   573  */
   574 #define	SMALL_MAX_2POW_DEFAULT	9
   575 #define	SMALL_MAX_DEFAULT	(1U << SMALL_MAX_2POW_DEFAULT)
   577 /*
   578  * RUN_MAX_OVRHD indicates maximum desired run header overhead.  Runs are sized
   579  * as small as possible such that this setting is still honored, without
   580  * violating other constraints.  The goal is to make runs as small as possible
   581  * without exceeding a per run external fragmentation threshold.
   582  *
   583  * We use binary fixed point math for overhead computations, where the binary
   584  * point is implicitly RUN_BFP bits to the left.
   585  *
   586  * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
   587  * honored for some/all object sizes, since there is one bit of header overhead
   588  * per object (plus a constant).  This constraint is relaxed (ignored) for runs
   589  * that are so small that the per-region overhead is greater than:
   590  *
   591  *   (RUN_MAX_OVRHD / (reg_size << (3+RUN_BFP))
   592  */
   593 #define	RUN_BFP			12
   594 /*                                    \/   Implicit binary fixed point. */
   595 #define	RUN_MAX_OVRHD		0x0000003dU
   596 #define	RUN_MAX_OVRHD_RELAX	0x00001800U
   598 /* Put a cap on small object run size.  This overrides RUN_MAX_OVRHD. */
   599 #define	RUN_MAX_SMALL_2POW	15
   600 #define	RUN_MAX_SMALL		(1U << RUN_MAX_SMALL_2POW)
   602 /*
   603  * Hyper-threaded CPUs may need a special instruction inside spin loops in
   604  * order to yield to another virtual CPU.  If no such instruction is defined
   605  * above, make CPU_SPINWAIT a no-op.
   606  */
   607 #ifndef CPU_SPINWAIT
   608 #  define CPU_SPINWAIT
   609 #endif
   611 /*
   612  * Adaptive spinning must eventually switch to blocking, in order to avoid the
   613  * potential for priority inversion deadlock.  Backing off past a certain point
   614  * can actually waste time.
   615  */
   616 #define	SPIN_LIMIT_2POW		11
   618 /*
   619  * Conversion from spinning to blocking is expensive; we use (1U <<
   620  * BLOCK_COST_2POW) to estimate how many more times costly blocking is than
   621  * worst-case spinning.
   622  */
   623 #define	BLOCK_COST_2POW		4
   625 #ifdef MALLOC_BALANCE
   626    /*
   627     * We use an exponential moving average to track recent lock contention,
   628     * where the size of the history window is N, and alpha=2/(N+1).
   629     *
   630     * Due to integer math rounding, very small values here can cause
   631     * substantial degradation in accuracy, thus making the moving average decay
   632     * faster than it would with precise calculation.
   633     */
   634 #  define BALANCE_ALPHA_INV_2POW	9
   636    /*
   637     * Threshold value for the exponential moving contention average at which to
   638     * re-assign a thread.
   639     */
   640 #  define BALANCE_THRESHOLD_DEFAULT	(1U << (SPIN_LIMIT_2POW-4))
   641 #endif
   643 /******************************************************************************/
   645 /* MALLOC_DECOMMIT and MALLOC_DOUBLE_PURGE are mutually exclusive. */
   646 #if defined(MALLOC_DECOMMIT) && defined(MALLOC_DOUBLE_PURGE)
   647 #error MALLOC_DECOMMIT and MALLOC_DOUBLE_PURGE are mutually exclusive.
   648 #endif
   650 /*
   651  * Mutexes based on spinlocks.  We can't use normal pthread spinlocks in all
   652  * places, because they require malloc()ed memory, which causes bootstrapping
   653  * issues in some cases.
   654  */
   655 #if defined(MOZ_MEMORY_WINDOWS)
   656 #define malloc_mutex_t CRITICAL_SECTION
   657 #define malloc_spinlock_t CRITICAL_SECTION
   658 #elif defined(MOZ_MEMORY_DARWIN)
   659 typedef struct {
   660 	OSSpinLock	lock;
   661 } malloc_mutex_t;
   662 typedef struct {
   663 	OSSpinLock	lock;
   664 } malloc_spinlock_t;
   665 #elif defined(MOZ_MEMORY)
   666 typedef pthread_mutex_t malloc_mutex_t;
   667 typedef pthread_mutex_t malloc_spinlock_t;
   668 #else
   669 /* XXX these should #ifdef these for freebsd (and linux?) only */
   670 typedef struct {
   671 	spinlock_t	lock;
   672 } malloc_mutex_t;
   673 typedef malloc_spinlock_t malloc_mutex_t;
   674 #endif
   676 /* Set to true once the allocator has been initialized. */
   677 static bool malloc_initialized = false;
   679 #if defined(MOZ_MEMORY_WINDOWS)
   680 /* No init lock for Windows. */
   681 #elif defined(MOZ_MEMORY_DARWIN)
   682 static malloc_mutex_t init_lock = {OS_SPINLOCK_INIT};
   683 #elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
   684 static malloc_mutex_t init_lock = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
   685 #elif defined(MOZ_MEMORY)
   686 static malloc_mutex_t init_lock = PTHREAD_MUTEX_INITIALIZER;
   687 #else
   688 static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER};
   689 #endif
   691 /******************************************************************************/
   692 /*
   693  * Statistics data structures.
   694  */
   696 #ifdef MALLOC_STATS
   698 typedef struct malloc_bin_stats_s malloc_bin_stats_t;
   699 struct malloc_bin_stats_s {
   700 	/*
   701 	 * Number of allocation requests that corresponded to the size of this
   702 	 * bin.
   703 	 */
   704 	uint64_t	nrequests;
   706 	/* Total number of runs created for this bin's size class. */
   707 	uint64_t	nruns;
   709 	/*
   710 	 * Total number of runs reused by extracting them from the runs tree for
   711 	 * this bin's size class.
   712 	 */
   713 	uint64_t	reruns;
   715 	/* High-water mark for this bin. */
   716 	unsigned long	highruns;
   718 	/* Current number of runs in this bin. */
   719 	unsigned long	curruns;
   720 };
   722 typedef struct arena_stats_s arena_stats_t;
   723 struct arena_stats_s {
   724 	/* Number of bytes currently mapped. */
   725 	size_t		mapped;
   727 	/*
   728 	 * Total number of purge sweeps, total number of madvise calls made,
   729 	 * and total pages purged in order to keep dirty unused memory under
   730 	 * control.
   731 	 */
   732 	uint64_t	npurge;
   733 	uint64_t	nmadvise;
   734 	uint64_t	purged;
   735 #ifdef MALLOC_DECOMMIT
   736 	/*
   737 	 * Total number of decommit/commit operations, and total number of
   738 	 * pages decommitted.
   739 	 */
   740 	uint64_t	ndecommit;
   741 	uint64_t	ncommit;
   742 	uint64_t	decommitted;
   743 #endif
   745 	/* Current number of committed pages. */
   746 	size_t		committed;
   748 	/* Per-size-category statistics. */
   749 	size_t		allocated_small;
   750 	uint64_t	nmalloc_small;
   751 	uint64_t	ndalloc_small;
   753 	size_t		allocated_large;
   754 	uint64_t	nmalloc_large;
   755 	uint64_t	ndalloc_large;
   757 #ifdef MALLOC_BALANCE
   758 	/* Number of times this arena reassigned a thread due to contention. */
   759 	uint64_t	nbalance;
   760 #endif
   761 };
   763 #endif /* #ifdef MALLOC_STATS */
   765 /******************************************************************************/
   766 /*
   767  * Extent data structures.
   768  */
   770 /* Tree of extents. */
   771 typedef struct extent_node_s extent_node_t;
   772 struct extent_node_s {
   773 	/* Linkage for the size/address-ordered tree. */
   774 	rb_node(extent_node_t) link_szad;
   776 	/* Linkage for the address-ordered tree. */
   777 	rb_node(extent_node_t) link_ad;
   779 	/* Pointer to the extent that this tree node is responsible for. */
   780 	void	*addr;
   782 	/* Total region size. */
   783 	size_t	size;
   784 };
   785 typedef rb_tree(extent_node_t) extent_tree_t;
   787 /******************************************************************************/
   788 /*
   789  * Radix tree data structures.
   790  */
   792 #ifdef MALLOC_VALIDATE
   793    /*
   794     * Size of each radix tree node (must be a power of 2).  This impacts tree
   795     * depth.
   796     */
   797 #  if (SIZEOF_PTR == 4)
   798 #    define MALLOC_RTREE_NODESIZE (1U << 14)
   799 #  else
   800 #    define MALLOC_RTREE_NODESIZE CACHELINE
   801 #  endif
   803 typedef struct malloc_rtree_s malloc_rtree_t;
   804 struct malloc_rtree_s {
   805 	malloc_spinlock_t	lock;
   806 	void			**root;
   807 	unsigned		height;
   808 	unsigned		level2bits[1]; /* Dynamically sized. */
   809 };
   810 #endif
   812 /******************************************************************************/
   813 /*
   814  * Arena data structures.
   815  */
   817 typedef struct arena_s arena_t;
   818 typedef struct arena_bin_s arena_bin_t;
   820 /* Each element of the chunk map corresponds to one page within the chunk. */
   821 typedef struct arena_chunk_map_s arena_chunk_map_t;
   822 struct arena_chunk_map_s {
   823 	/*
   824 	 * Linkage for run trees.  There are two disjoint uses:
   825 	 *
   826 	 * 1) arena_t's runs_avail tree.
   827 	 * 2) arena_run_t conceptually uses this linkage for in-use non-full
   828 	 *    runs, rather than directly embedding linkage.
   829 	 */
   830 	rb_node(arena_chunk_map_t)	link;
   832 	/*
   833 	 * Run address (or size) and various flags are stored together.  The bit
   834 	 * layout looks like (assuming 32-bit system):
   835 	 *
   836 	 *   ???????? ???????? ????---- -mckdzla
   837 	 *
   838 	 * ? : Unallocated: Run address for first/last pages, unset for internal
   839 	 *                  pages.
   840 	 *     Small: Run address.
   841 	 *     Large: Run size for first page, unset for trailing pages.
   842 	 * - : Unused.
   843 	 * m : MADV_FREE/MADV_DONTNEED'ed?
   844 	 * c : decommitted?
   845 	 * k : key?
   846 	 * d : dirty?
   847 	 * z : zeroed?
   848 	 * l : large?
   849 	 * a : allocated?
   850 	 *
   851 	 * Following are example bit patterns for the three types of runs.
   852 	 *
   853 	 * r : run address
   854 	 * s : run size
   855 	 * x : don't care
   856 	 * - : 0
   857 	 * [cdzla] : bit set
   858 	 *
   859 	 *   Unallocated:
   860 	 *     ssssssss ssssssss ssss---- --c-----
   861 	 *     xxxxxxxx xxxxxxxx xxxx---- ----d---
   862 	 *     ssssssss ssssssss ssss---- -----z--
   863 	 *
   864 	 *   Small:
   865 	 *     rrrrrrrr rrrrrrrr rrrr---- -------a
   866 	 *     rrrrrrrr rrrrrrrr rrrr---- -------a
   867 	 *     rrrrrrrr rrrrrrrr rrrr---- -------a
   868 	 *
   869 	 *   Large:
   870 	 *     ssssssss ssssssss ssss---- ------la
   871 	 *     -------- -------- -------- ------la
   872 	 *     -------- -------- -------- ------la
   873 	 */
   874 	size_t				bits;
   876 /* Note that CHUNK_MAP_DECOMMITTED's meaning varies depending on whether
   877  * MALLOC_DECOMMIT and MALLOC_DOUBLE_PURGE are defined.
   878  *
   879  * If MALLOC_DECOMMIT is defined, a page which is CHUNK_MAP_DECOMMITTED must be
   880  * re-committed with pages_commit() before it may be touched.  If
   881  * MALLOC_DECOMMIT is defined, MALLOC_DOUBLE_PURGE may not be defined.
   882  *
   883  * If neither MALLOC_DECOMMIT nor MALLOC_DOUBLE_PURGE is defined, pages which
   884  * are madvised (with either MADV_DONTNEED or MADV_FREE) are marked with
   885  * CHUNK_MAP_MADVISED.
   886  *
   887  * Otherwise, if MALLOC_DECOMMIT is not defined and MALLOC_DOUBLE_PURGE is
   888  * defined, then a page which is madvised is marked as CHUNK_MAP_MADVISED.
   889  * When it's finally freed with jemalloc_purge_freed_pages, the page is marked
   890  * as CHUNK_MAP_DECOMMITTED.
   891  */
   892 #if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS) || defined(MALLOC_DOUBLE_PURGE)
   893 #define	CHUNK_MAP_MADVISED	((size_t)0x40U)
   894 #define	CHUNK_MAP_DECOMMITTED	((size_t)0x20U)
   895 #define	CHUNK_MAP_MADVISED_OR_DECOMMITTED (CHUNK_MAP_MADVISED | CHUNK_MAP_DECOMMITTED)
   896 #endif
   897 #define	CHUNK_MAP_KEY		((size_t)0x10U)
   898 #define	CHUNK_MAP_DIRTY		((size_t)0x08U)
   899 #define	CHUNK_MAP_ZEROED	((size_t)0x04U)
   900 #define	CHUNK_MAP_LARGE		((size_t)0x02U)
   901 #define	CHUNK_MAP_ALLOCATED	((size_t)0x01U)
   902 };
   903 typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;
   904 typedef rb_tree(arena_chunk_map_t) arena_run_tree_t;
   906 /* Arena chunk header. */
   907 typedef struct arena_chunk_s arena_chunk_t;
   908 struct arena_chunk_s {
   909 	/* Arena that owns the chunk. */
   910 	arena_t		*arena;
   912 	/* Linkage for the arena's chunks_dirty tree. */
   913 	rb_node(arena_chunk_t) link_dirty;
   915 #ifdef MALLOC_DOUBLE_PURGE
   916 	/* If we're double-purging, we maintain a linked list of chunks which
   917 	 * have pages which have been madvise(MADV_FREE)'d but not explicitly
   918 	 * purged.
   919 	 *
   920 	 * We're currently lazy and don't remove a chunk from this list when
   921 	 * all its madvised pages are recommitted. */
   922 	LinkedList	chunks_madvised_elem;
   923 #endif
   925 	/* Number of dirty pages. */
   926 	size_t		ndirty;
   928 	/* Map of pages within chunk that keeps track of free/large/small. */
   929 	arena_chunk_map_t map[1]; /* Dynamically sized. */
   930 };
   931 typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
   933 typedef struct arena_run_s arena_run_t;
   934 struct arena_run_s {
   935 #if defined(MALLOC_DEBUG) || defined(MOZ_JEMALLOC_HARD_ASSERTS)
   936 	uint32_t	magic;
   937 #  define ARENA_RUN_MAGIC 0x384adf93
   938 #endif
   940 	/* Bin this run is associated with. */
   941 	arena_bin_t	*bin;
   943 	/* Index of first element that might have a free region. */
   944 	unsigned	regs_minelm;
   946 	/* Number of free regions in run. */
   947 	unsigned	nfree;
   949 	/* Bitmask of in-use regions (0: in use, 1: free). */
   950 	unsigned	regs_mask[1]; /* Dynamically sized. */
   951 };
   953 struct arena_bin_s {
   954 	/*
   955 	 * Current run being used to service allocations of this bin's size
   956 	 * class.
   957 	 */
   958 	arena_run_t	*runcur;
   960 	/*
   961 	 * Tree of non-full runs.  This tree is used when looking for an
   962 	 * existing run when runcur is no longer usable.  We choose the
   963 	 * non-full run that is lowest in memory; this policy tends to keep
   964 	 * objects packed well, and it can also help reduce the number of
   965 	 * almost-empty chunks.
   966 	 */
   967 	arena_run_tree_t runs;
   969 	/* Size of regions in a run for this bin's size class. */
   970 	size_t		reg_size;
   972 	/* Total size of a run for this bin's size class. */
   973 	size_t		run_size;
   975 	/* Total number of regions in a run for this bin's size class. */
   976 	uint32_t	nregs;
   978 	/* Number of elements in a run's regs_mask for this bin's size class. */
   979 	uint32_t	regs_mask_nelms;
   981 	/* Offset of first region in a run for this bin's size class. */
   982 	uint32_t	reg0_offset;
   984 #ifdef MALLOC_STATS
   985 	/* Bin statistics. */
   986 	malloc_bin_stats_t stats;
   987 #endif
   988 };
   990 struct arena_s {
   991 #if defined(MALLOC_DEBUG) || defined(MOZ_JEMALLOC_HARD_ASSERTS)
   992 	uint32_t		magic;
   993 #  define ARENA_MAGIC 0x947d3d24
   994 #endif
   996 	/* All operations on this arena require that lock be locked. */
   997 #ifdef MOZ_MEMORY
   998 	malloc_spinlock_t	lock;
   999 #else
  1000 	pthread_mutex_t		lock;
  1001 #endif
  1003 #ifdef MALLOC_STATS
  1004 	arena_stats_t		stats;
  1005 #endif
  1007 	/* Tree of dirty-page-containing chunks this arena manages. */
  1008 	arena_chunk_tree_t	chunks_dirty;
  1010 #ifdef MALLOC_DOUBLE_PURGE
  1011 	/* Head of a linked list of MADV_FREE'd-page-containing chunks this
  1012 	 * arena manages. */
  1013 	LinkedList		chunks_madvised;
  1014 #endif
  1016 	/*
  1017 	 * In order to avoid rapid chunk allocation/deallocation when an arena
  1018 	 * oscillates right on the cusp of needing a new chunk, cache the most
  1019 	 * recently freed chunk.  The spare is left in the arena's chunk trees
  1020 	 * until it is deleted.
  1022 	 * There is one spare chunk per arena, rather than one spare total, in
  1023 	 * order to avoid interactions between multiple threads that could make
  1024 	 * a single spare inadequate.
  1025 	 */
  1026 	arena_chunk_t		*spare;
  1028 	/*
  1029 	 * Current count of pages within unused runs that are potentially
  1030 	 * dirty, and for which madvise(... MADV_FREE) has not been called.  By
  1031 	 * tracking this, we can institute a limit on how much dirty unused
  1032 	 * memory is mapped for each arena.
  1033 	 */
  1034 	size_t			ndirty;
  1036 	/*
  1037 	 * Size/address-ordered tree of this arena's available runs.  This tree
  1038 	 * is used for first-best-fit run allocation.
  1039 	 */
  1040 	arena_avail_tree_t	runs_avail;
  1042 #ifdef MALLOC_BALANCE
  1043 	/*
  1044 	 * The arena load balancing machinery needs to keep track of how much
  1045 	 * lock contention there is.  This value is exponentially averaged.
  1046 	 */
  1047 	uint32_t		contention;
  1048 #endif
  1050 	/*
  1051 	 * bins is used to store rings of free regions of the following sizes,
  1052 	 * assuming a 16-byte quantum, 4kB pagesize, and default MALLOC_OPTIONS.
  1054 	 *   bins[i] | size |
  1055 	 *   --------+------+
  1056 	 *        0  |    2 |
  1057 	 *        1  |    4 |
  1058 	 *        2  |    8 |
  1059 	 *   --------+------+
  1060 	 *        3  |   16 |
  1061 	 *        4  |   32 |
  1062 	 *        5  |   48 |
  1063 	 *        6  |   64 |
  1064 	 *           :      :
  1065 	 *           :      :
  1066 	 *       33  |  496 |
  1067 	 *       34  |  512 |
  1068 	 *   --------+------+
  1069 	 *       35  | 1024 |
  1070 	 *       36  | 2048 |
  1071 	 *   --------+------+
  1072 	 */
  1073 	arena_bin_t		bins[1]; /* Dynamically sized. */
  1074 };
  1076 /******************************************************************************/
  1077 /*
  1078  * Data.
  1079  */
  1081 #ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
  1082 /* Number of CPUs. */
  1083 static unsigned		ncpus;
  1084 #endif
  1086 /*
  1087  * When MALLOC_STATIC_SIZES is defined most of the parameters
  1088  * controlling the malloc behavior are defined as compile-time constants
  1089  * for best performance and cannot be altered at runtime.
  1090  */
  1091 #if !defined(__ia64__) && !defined(__sparc__) && !defined(__mips__)
  1092 #define MALLOC_STATIC_SIZES 1
  1093 #endif
  1095 #ifdef MALLOC_STATIC_SIZES
  1097 /*
  1098  * VM page size. It must divide the runtime CPU page size or the code
  1099  * will abort.
  1100  * Platform specific page size conditions copied from js/public/HeapAPI.h
  1101  */
  1102 #if (defined(SOLARIS) || defined(__FreeBSD__)) && \
  1103     (defined(__sparc) || defined(__sparcv9) || defined(__ia64))
  1104 #define pagesize_2pow			((size_t) 13)
  1105 #elif defined(__powerpc64__) || defined(__aarch64__)
  1106 #define pagesize_2pow			((size_t) 16)
  1107 #else
  1108 #define pagesize_2pow			((size_t) 12)
  1109 #endif
  1110 #define pagesize			((size_t) 1 << pagesize_2pow)
  1111 #define pagesize_mask			(pagesize - 1)
  1113 /* Various quantum-related settings. */
  1115 #define QUANTUM_DEFAULT 		((size_t) 1 << QUANTUM_2POW_MIN)
  1116 static const size_t	quantum	=	QUANTUM_DEFAULT;
  1117 static const size_t	quantum_mask =	QUANTUM_DEFAULT - 1;
  1119 /* Various bin-related settings. */
  1121 static const size_t	small_min =	(QUANTUM_DEFAULT >> 1) + 1;
  1122 static const size_t	small_max =	(size_t) SMALL_MAX_DEFAULT;
  1124 /* Max size class for bins. */
  1125 static const size_t	bin_maxclass =	pagesize >> 1;
  1127  /* Number of (2^n)-spaced tiny bins. */
  1128 static const unsigned	ntbins =	(unsigned)
  1129 					(QUANTUM_2POW_MIN - TINY_MIN_2POW);
  1131  /* Number of quantum-spaced bins. */
  1132 static const unsigned	nqbins =	(unsigned)
  1133 					(SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN);
  1135 /* Number of (2^n)-spaced sub-page bins. */
  1136 static const unsigned	nsbins =	(unsigned)
  1137 					(pagesize_2pow -
  1138 					 SMALL_MAX_2POW_DEFAULT - 1);
  1140 #else /* !MALLOC_STATIC_SIZES */
  1142 /* VM page size. */
  1143 static size_t		pagesize;
  1144 static size_t		pagesize_mask;
  1145 static size_t		pagesize_2pow;
  1147 /* Various bin-related settings. */
  1148 static size_t		bin_maxclass; /* Max size class for bins. */
  1149 static unsigned		ntbins; /* Number of (2^n)-spaced tiny bins. */
  1150 static unsigned		nqbins; /* Number of quantum-spaced bins. */
  1151 static unsigned		nsbins; /* Number of (2^n)-spaced sub-page bins. */
  1152 static size_t		small_min;
  1153 static size_t		small_max;
  1155 /* Various quantum-related settings. */
  1156 static size_t		quantum;
  1157 static size_t		quantum_mask; /* (quantum - 1). */
  1159 #endif
  1161 /* Various chunk-related settings. */
  1163 /*
  1164  * Compute the header size such that it is large enough to contain the page map
  1165  * and enough nodes for the worst case: one node per non-header page plus one
  1166  * extra for situations where we briefly have one more node allocated than we
  1167  * will need.
  1168  */
  1169 #define calculate_arena_header_size()					\
  1170 	(sizeof(arena_chunk_t) + sizeof(arena_chunk_map_t) * (chunk_npages - 1))
  1172 #define calculate_arena_header_pages()					\
  1173 	((calculate_arena_header_size() >> pagesize_2pow) +		\
  1174 	 ((calculate_arena_header_size() & pagesize_mask) ? 1 : 0))
  1176 /* Max size class for arenas. */
  1177 #define calculate_arena_maxclass()					\
  1178 	(chunksize - (arena_chunk_header_npages << pagesize_2pow))
  1180 #ifdef MALLOC_STATIC_SIZES
  1181 #define CHUNKSIZE_DEFAULT		((size_t) 1 << CHUNK_2POW_DEFAULT)
  1182 static const size_t	chunksize =	CHUNKSIZE_DEFAULT;
  1183 static const size_t	chunksize_mask =CHUNKSIZE_DEFAULT - 1;
  1184 static const size_t	chunk_npages =	CHUNKSIZE_DEFAULT >> pagesize_2pow;
  1185 #define arena_chunk_header_npages	calculate_arena_header_pages()
  1186 #define arena_maxclass			calculate_arena_maxclass()
  1187 #else
  1188 static size_t		chunksize;
  1189 static size_t		chunksize_mask; /* (chunksize - 1). */
  1190 static size_t		chunk_npages;
  1191 static size_t		arena_chunk_header_npages;
  1192 static size_t		arena_maxclass; /* Max size class for arenas. */
  1193 #endif
  1195 /********/
  1196 /*
  1197  * Chunks.
  1198  */
  1200 #ifdef MALLOC_VALIDATE
  1201 static malloc_rtree_t *chunk_rtree;
  1202 #endif
  1204 /* Protects chunk-related data structures. */
  1205 static malloc_mutex_t	huge_mtx;
  1207 /* Tree of chunks that are stand-alone huge allocations. */
  1208 static extent_tree_t	huge;
  1210 #ifdef MALLOC_STATS
  1211 /* Huge allocation statistics. */
  1212 static uint64_t		huge_nmalloc;
  1213 static uint64_t		huge_ndalloc;
  1214 static size_t		huge_allocated;
  1215 static size_t		huge_mapped;
  1216 #endif
  1218 #ifdef MALLOC_PAGEFILE
  1219 static char		pagefile_templ[PATH_MAX];
  1220 #endif
  1222 /****************************/
  1223 /*
  1224  * base (internal allocation).
  1225  */
  1227 /*
  1228  * Current pages that are being used for internal memory allocations.  These
  1229  * pages are carved up in cacheline-size quanta, so that there is no chance of
  1230  * false cache line sharing.
  1231  */
  1232 static void		*base_pages;
  1233 static void		*base_next_addr;
  1234 #if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS)
  1235 static void		*base_next_decommitted;
  1236 #endif
  1237 static void		*base_past_addr; /* Addr immediately past base_pages. */
  1238 static extent_node_t	*base_nodes;
  1239 static malloc_mutex_t	base_mtx;
  1240 #ifdef MALLOC_STATS
  1241 static size_t		base_mapped;
  1242 static size_t		base_committed;
  1243 #endif
  1245 /********/
  1246 /*
  1247  * Arenas.
  1248  */
  1250 /*
  1251  * Arenas that are used to service external requests.  Not all elements of the
  1252  * arenas array are necessarily used; arenas are created lazily as needed.
  1253  */
  1254 static arena_t		**arenas;
  1255 static unsigned		narenas;
  1256 #ifndef NO_TLS
  1257 #  ifdef MALLOC_BALANCE
  1258 static unsigned		narenas_2pow;
  1259 #  else
  1260 static unsigned		next_arena;
  1261 #  endif
  1262 #endif
  1263 #ifdef MOZ_MEMORY
  1264 static malloc_spinlock_t arenas_lock; /* Protects arenas initialization. */
  1265 #else
  1266 static pthread_mutex_t arenas_lock; /* Protects arenas initialization. */
  1267 #endif
  1269 #ifndef NO_TLS
  1270 /*
  1271  * Map of pthread_self() --> arenas[???], used for selecting an arena to use
  1272  * for allocations.
  1273  */
  1274 #ifndef MOZ_MEMORY_WINDOWS
  1275 static __thread arena_t	*arenas_map;
  1276 #endif
  1277 #endif
  1279 /*******************************/
  1280 /*
  1281  * Runtime configuration options.
  1282  */
  1283 MOZ_JEMALLOC_API
  1284 const char	*_malloc_options = MOZ_MALLOC_OPTIONS;
  1286 #ifndef MALLOC_PRODUCTION
  1287 static bool	opt_abort = true;
  1288 #ifdef MALLOC_FILL
  1289 static bool	opt_junk = true;
  1290 static bool	opt_poison = true;
  1291 static bool	opt_zero = false;
  1292 #endif
  1293 #else
  1294 static bool	opt_abort = false;
  1295 #ifdef MALLOC_FILL
  1296 static const bool	opt_junk = false;
  1297 static const bool	opt_poison = true;
  1298 static const bool	opt_zero = false;
  1299 #endif
  1300 #endif
  1302 static size_t	opt_dirty_max = DIRTY_MAX_DEFAULT;
  1303 #ifdef MALLOC_BALANCE
  1304 static uint64_t	opt_balance_threshold = BALANCE_THRESHOLD_DEFAULT;
  1305 #endif
  1306 static bool	opt_print_stats = false;
  1307 #ifdef MALLOC_STATIC_SIZES
  1308 #define opt_quantum_2pow	QUANTUM_2POW_MIN
  1309 #define opt_small_max_2pow	SMALL_MAX_2POW_DEFAULT
  1310 #define opt_chunk_2pow		CHUNK_2POW_DEFAULT
  1311 #else
  1312 static size_t	opt_quantum_2pow = QUANTUM_2POW_MIN;
  1313 static size_t	opt_small_max_2pow = SMALL_MAX_2POW_DEFAULT;
  1314 static size_t	opt_chunk_2pow = CHUNK_2POW_DEFAULT;
  1315 #endif
  1316 #ifdef MALLOC_PAGEFILE
  1317 static bool	opt_pagefile = false;
  1318 #endif
  1319 #ifdef MALLOC_UTRACE
  1320 static bool	opt_utrace = false;
  1321 #endif
  1322 #ifdef MALLOC_SYSV
  1323 static bool	opt_sysv = false;
  1324 #endif
  1325 #ifdef MALLOC_XMALLOC
  1326 static bool	opt_xmalloc = false;
  1327 #endif
  1328 static int	opt_narenas_lshift = 0;
  1330 #ifdef MALLOC_UTRACE
  1331 typedef struct {
  1332 	void	*p;
  1333 	size_t	s;
  1334 	void	*r;
  1335 } malloc_utrace_t;
  1337 #define	UTRACE(a, b, c)							\
  1338 	if (opt_utrace) {						\
  1339 		malloc_utrace_t ut;					\
  1340 		ut.p = (a);						\
  1341 		ut.s = (b);						\
  1342 		ut.r = (c);						\
  1343 		utrace(&ut, sizeof(ut));				\
  1345 #else
  1346 #define	UTRACE(a, b, c)
  1347 #endif
  1349 /******************************************************************************/
  1350 /*
  1351  * Begin function prototypes for non-inline static functions.
  1352  */
  1354 static char	*umax2s(uintmax_t x, unsigned base, char *s);
  1355 static bool	malloc_mutex_init(malloc_mutex_t *mutex);
  1356 static bool	malloc_spin_init(malloc_spinlock_t *lock);
  1357 static void	wrtmessage(const char *p1, const char *p2, const char *p3,
  1358 		const char *p4);
  1359 #ifdef MALLOC_STATS
  1360 #ifdef MOZ_MEMORY_DARWIN
  1361 /* Avoid namespace collision with OS X's malloc APIs. */
  1362 #define malloc_printf moz_malloc_printf
  1363 #endif
  1364 static void	malloc_printf(const char *format, ...);
  1365 #endif
  1366 static bool	base_pages_alloc_mmap(size_t minsize);
  1367 static bool	base_pages_alloc(size_t minsize);
  1368 static void	*base_alloc(size_t size);
  1369 static void	*base_calloc(size_t number, size_t size);
  1370 static extent_node_t *base_node_alloc(void);
  1371 static void	base_node_dealloc(extent_node_t *node);
  1372 #ifdef MALLOC_STATS
  1373 static void	stats_print(arena_t *arena);
  1374 #endif
  1375 static void	*pages_map(void *addr, size_t size, int pfd);
  1376 static void	pages_unmap(void *addr, size_t size);
  1377 static void	*chunk_alloc_mmap(size_t size, bool pagefile);
  1378 #ifdef MALLOC_PAGEFILE
  1379 static int	pagefile_init(size_t size);
  1380 static void	pagefile_close(int pfd);
  1381 #endif
  1382 static void	*chunk_alloc(size_t size, bool zero, bool pagefile);
  1383 static void	chunk_dealloc_mmap(void *chunk, size_t size);
  1384 static void	chunk_dealloc(void *chunk, size_t size);
  1385 #ifndef NO_TLS
  1386 static arena_t	*choose_arena_hard(void);
  1387 #endif
  1388 static void	arena_run_split(arena_t *arena, arena_run_t *run, size_t size,
  1389     bool large, bool zero);
  1390 static void arena_chunk_init(arena_t *arena, arena_chunk_t *chunk);
  1391 static void	arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk);
  1392 static arena_run_t *arena_run_alloc(arena_t *arena, arena_bin_t *bin,
  1393     size_t size, bool large, bool zero);
  1394 static void	arena_purge(arena_t *arena, bool all);
  1395 static void	arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty);
  1396 static void	arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk,
  1397     arena_run_t *run, size_t oldsize, size_t newsize);
  1398 static void	arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk,
  1399     arena_run_t *run, size_t oldsize, size_t newsize, bool dirty);
  1400 static arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin);
  1401 static void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin);
  1402 static size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size);
  1403 #ifdef MALLOC_BALANCE
  1404 static void	arena_lock_balance_hard(arena_t *arena);
  1405 #endif
  1406 static void	*arena_malloc_large(arena_t *arena, size_t size, bool zero);
  1407 static void	*arena_palloc(arena_t *arena, size_t alignment, size_t size,
  1408     size_t alloc_size);
  1409 static size_t	arena_salloc(const void *ptr);
  1410 static void	arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk,
  1411     void *ptr);
  1412 static void	arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk,
  1413     void *ptr, size_t size, size_t oldsize);
  1414 static bool	arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk,
  1415     void *ptr, size_t size, size_t oldsize);
  1416 static bool	arena_ralloc_large(void *ptr, size_t size, size_t oldsize);
  1417 static void	*arena_ralloc(void *ptr, size_t size, size_t oldsize);
  1418 static bool	arena_new(arena_t *arena);
  1419 static arena_t	*arenas_extend(unsigned ind);
  1420 static void	*huge_malloc(size_t size, bool zero);
  1421 static void	*huge_palloc(size_t alignment, size_t size);
  1422 static void	*huge_ralloc(void *ptr, size_t size, size_t oldsize);
  1423 static void	huge_dalloc(void *ptr);
  1424 static void	malloc_print_stats(void);
  1425 #ifndef MOZ_MEMORY_WINDOWS
  1426 static
  1427 #endif
  1428 bool		malloc_init_hard(void);
  1430 static void	_malloc_prefork(void);
  1431 static void	_malloc_postfork(void);
  1433 #ifdef MOZ_MEMORY_DARWIN
  1434 /*
  1435  * MALLOC_ZONE_T_NOTE
  1437  * On Darwin, we hook into the memory allocator using a malloc_zone_t struct.
  1438  * We must be very careful around this struct because of different behaviour on
  1439  * different versions of OSX.
  1441  * Each of OSX 10.5, 10.6 and 10.7 use different versions of the struct
  1442  * (with version numbers 3, 6 and 8 respectively). The binary we use on each of
  1443  * these platforms will not necessarily be built using the correct SDK [1].
  1444  * This means we need to statically know the correct struct size to use on all
  1445  * OSX releases, and have a fallback for unknown future versions. The struct
  1446  * sizes defined in osx_zone_types.h.
  1448  * For OSX 10.8 and later, we may expect the malloc_zone_t struct to change
  1449  * again, and need to dynamically account for this. By simply leaving
  1450  * malloc_zone_t alone, we don't quite deal with the problem, because there
  1451  * remain calls to jemalloc through the mozalloc interface. We check this
  1452  * dynamically on each allocation, using the CHECK_DARWIN macro and
  1453  * osx_use_jemalloc.
  1456  * [1] Mozilla is built as a universal binary on Mac, supporting i386 and
  1457  *     x86_64. The i386 target is built using the 10.5 SDK, even if it runs on
  1458  *     10.6. The x86_64 target is built using the 10.6 SDK, even if it runs on
  1459  *     10.7 or later, or 10.5.
  1461  * FIXME:
  1462  *   When later versions of OSX come out (10.8 and up), we need to check their
  1463  *   malloc_zone_t versions. If they're greater than 8, we need a new version
  1464  *   of malloc_zone_t adapted into osx_zone_types.h.
  1465  */
  1467 #ifndef MOZ_REPLACE_MALLOC
  1468 #include "osx_zone_types.h"
  1470 #define LEOPARD_MALLOC_ZONE_T_VERSION 3
  1471 #define SNOW_LEOPARD_MALLOC_ZONE_T_VERSION 6
  1472 #define LION_MALLOC_ZONE_T_VERSION 8
  1474 static bool osx_use_jemalloc = false;
  1477 static lion_malloc_zone l_szone;
  1478 static malloc_zone_t * szone = (malloc_zone_t*)(&l_szone);
  1480 static lion_malloc_introspection l_ozone_introspect;
  1481 static malloc_introspection_t * const ozone_introspect =
  1482 	(malloc_introspection_t*)(&l_ozone_introspect);
  1483 static void szone2ozone(malloc_zone_t *zone, size_t size);
  1484 static size_t zone_version_size(int version);
  1485 #else
  1486 static const bool osx_use_jemalloc = true;
  1487 #endif
  1489 #endif
  1491 /*
  1492  * End function prototypes.
  1493  */
  1494 /******************************************************************************/
  1496 /*
  1497  * umax2s() provides minimal integer printing functionality, which is
  1498  * especially useful for situations where allocation in vsnprintf() calls would
  1499  * potentially cause deadlock.
  1500  */
  1501 #define	UMAX2S_BUFSIZE	65
  1502 char *
  1503 umax2s(uintmax_t x, unsigned base, char *s)
  1505 	unsigned i;
  1507 	i = UMAX2S_BUFSIZE - 1;
  1508 	s[i] = '\0';
  1509 	switch (base) {
  1510 	case 10:
  1511 		do {
  1512 			i--;
  1513 			s[i] = "0123456789"[x % 10];
  1514 			x /= 10;
  1515 		} while (x > 0);
  1516 		break;
  1517 	case 16:
  1518 		do {
  1519 			i--;
  1520 			s[i] = "0123456789abcdef"[x & 0xf];
  1521 			x >>= 4;
  1522 		} while (x > 0);
  1523 		break;
  1524 	default:
  1525 		do {
  1526 			i--;
  1527 			s[i] = "0123456789abcdefghijklmnopqrstuvwxyz"[x % base];
  1528 			x /= base;
  1529 		} while (x > 0);
  1532 	return (&s[i]);
  1535 static void
  1536 wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
  1538 #if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_WINDOWS)
  1539 #define	_write	write
  1540 #endif
  1541 	_write(STDERR_FILENO, p1, (unsigned int) strlen(p1));
  1542 	_write(STDERR_FILENO, p2, (unsigned int) strlen(p2));
  1543 	_write(STDERR_FILENO, p3, (unsigned int) strlen(p3));
  1544 	_write(STDERR_FILENO, p4, (unsigned int) strlen(p4));
  1547 MOZ_JEMALLOC_API
  1548 void	(*_malloc_message)(const char *p1, const char *p2, const char *p3,
  1549 	    const char *p4) = wrtmessage;
  1551 #ifdef MALLOC_DEBUG
  1552 #  define assert(e) do {						\
  1553 	if (!(e)) {							\
  1554 		char line_buf[UMAX2S_BUFSIZE];				\
  1555 		_malloc_message(__FILE__, ":", umax2s(__LINE__, 10,	\
  1556 		    line_buf), ": Failed assertion: ");			\
  1557 		_malloc_message("\"", #e, "\"\n", "");			\
  1558 		abort();						\
  1559 	}								\
  1560 } while (0)
  1561 #else
  1562 #define assert(e)
  1563 #endif
  1565 #include <mozilla/Assertions.h>
  1566 #include <mozilla/Attributes.h>
  1568 /* RELEASE_ASSERT calls jemalloc_crash() instead of calling MOZ_CRASH()
  1569  * directly because we want crashing to add a frame to the stack.  This makes
  1570  * it easier to find the failing assertion in crash stacks. */
  1571 MOZ_NEVER_INLINE static void
  1572 jemalloc_crash()
  1574 	MOZ_CRASH();
  1577 #if defined(MOZ_JEMALLOC_HARD_ASSERTS)
  1578 #  define RELEASE_ASSERT(assertion) do {	\
  1579 	if (!(assertion)) {			\
  1580 		jemalloc_crash();		\
  1581 	}					\
  1582 } while (0)
  1583 #else
  1584 #  define RELEASE_ASSERT(assertion) assert(assertion)
  1585 #endif
  1587 /******************************************************************************/
  1588 /*
  1589  * Begin mutex.  We can't use normal pthread mutexes in all places, because
  1590  * they require malloc()ed memory, which causes bootstrapping issues in some
  1591  * cases.
  1592  */
  1594 static bool
  1595 malloc_mutex_init(malloc_mutex_t *mutex)
  1597 #if defined(MOZ_MEMORY_WINDOWS)
  1598 	if (isthreaded)
  1599 		if (! __crtInitCritSecAndSpinCount(mutex, _CRT_SPINCOUNT))
  1600 			return (true);
  1601 #elif defined(MOZ_MEMORY_DARWIN)
  1602 	mutex->lock = OS_SPINLOCK_INIT;
  1603 #elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
  1604 	pthread_mutexattr_t attr;
  1605 	if (pthread_mutexattr_init(&attr) != 0)
  1606 		return (true);
  1607 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
  1608 	if (pthread_mutex_init(mutex, &attr) != 0) {
  1609 		pthread_mutexattr_destroy(&attr);
  1610 		return (true);
  1612 	pthread_mutexattr_destroy(&attr);
  1613 #elif defined(MOZ_MEMORY)
  1614 	if (pthread_mutex_init(mutex, NULL) != 0)
  1615 		return (true);
  1616 #else
  1617 	static const spinlock_t lock = _SPINLOCK_INITIALIZER;
  1619 	mutex->lock = lock;
  1620 #endif
  1621 	return (false);
  1624 static inline void
  1625 malloc_mutex_lock(malloc_mutex_t *mutex)
  1628 #if defined(MOZ_MEMORY_WINDOWS)
  1629 	EnterCriticalSection(mutex);
  1630 #elif defined(MOZ_MEMORY_DARWIN)
  1631 	OSSpinLockLock(&mutex->lock);
  1632 #elif defined(MOZ_MEMORY)
  1633 	pthread_mutex_lock(mutex);
  1634 #else
  1635 	if (isthreaded)
  1636 		_SPINLOCK(&mutex->lock);
  1637 #endif
  1640 static inline void
  1641 malloc_mutex_unlock(malloc_mutex_t *mutex)
  1644 #if defined(MOZ_MEMORY_WINDOWS)
  1645 	LeaveCriticalSection(mutex);
  1646 #elif defined(MOZ_MEMORY_DARWIN)
  1647 	OSSpinLockUnlock(&mutex->lock);
  1648 #elif defined(MOZ_MEMORY)
  1649 	pthread_mutex_unlock(mutex);
  1650 #else
  1651 	if (isthreaded)
  1652 		_SPINUNLOCK(&mutex->lock);
  1653 #endif
  1656 static bool
  1657 malloc_spin_init(malloc_spinlock_t *lock)
  1659 #if defined(MOZ_MEMORY_WINDOWS)
  1660 	if (isthreaded)
  1661 		if (! __crtInitCritSecAndSpinCount(lock, _CRT_SPINCOUNT))
  1662 			return (true);
  1663 #elif defined(MOZ_MEMORY_DARWIN)
  1664 	lock->lock = OS_SPINLOCK_INIT;
  1665 #elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
  1666 	pthread_mutexattr_t attr;
  1667 	if (pthread_mutexattr_init(&attr) != 0)
  1668 		return (true);
  1669 	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
  1670 	if (pthread_mutex_init(lock, &attr) != 0) {
  1671 		pthread_mutexattr_destroy(&attr);
  1672 		return (true);
  1674 	pthread_mutexattr_destroy(&attr);
  1675 #elif defined(MOZ_MEMORY)
  1676 	if (pthread_mutex_init(lock, NULL) != 0)
  1677 		return (true);
  1678 #else
  1679 	lock->lock = _SPINLOCK_INITIALIZER;
  1680 #endif
  1681 	return (false);
  1684 static inline void
  1685 malloc_spin_lock(malloc_spinlock_t *lock)
  1688 #if defined(MOZ_MEMORY_WINDOWS)
  1689 	EnterCriticalSection(lock);
  1690 #elif defined(MOZ_MEMORY_DARWIN)
  1691 	OSSpinLockLock(&lock->lock);
  1692 #elif defined(MOZ_MEMORY)
  1693 	pthread_mutex_lock(lock);
  1694 #else
  1695 	if (isthreaded)
  1696 		_SPINLOCK(&lock->lock);
  1697 #endif
  1700 static inline void
  1701 malloc_spin_unlock(malloc_spinlock_t *lock)
  1703 #if defined(MOZ_MEMORY_WINDOWS)
  1704 	LeaveCriticalSection(lock);
  1705 #elif defined(MOZ_MEMORY_DARWIN)
  1706 	OSSpinLockUnlock(&lock->lock);
  1707 #elif defined(MOZ_MEMORY)
  1708 	pthread_mutex_unlock(lock);
  1709 #else
  1710 	if (isthreaded)
  1711 		_SPINUNLOCK(&lock->lock);
  1712 #endif
  1715 /*
  1716  * End mutex.
  1717  */
  1718 /******************************************************************************/
  1719 /*
  1720  * Begin spin lock.  Spin locks here are actually adaptive mutexes that block
  1721  * after a period of spinning, because unbounded spinning would allow for
  1722  * priority inversion.
  1723  */
  1725 #if defined(MOZ_MEMORY) && !defined(MOZ_MEMORY_DARWIN)
  1726 #  define	malloc_spin_init	malloc_mutex_init
  1727 #  define	malloc_spin_lock	malloc_mutex_lock
  1728 #  define	malloc_spin_unlock	malloc_mutex_unlock
  1729 #endif
  1731 #ifndef MOZ_MEMORY
  1732 /*
  1733  * We use an unpublished interface to initialize pthread mutexes with an
  1734  * allocation callback, in order to avoid infinite recursion.
  1735  */
  1736 int	_pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
  1737     void *(calloc_cb)(size_t, size_t));
  1739 __weak_reference(_pthread_mutex_init_calloc_cb_stub,
  1740     _pthread_mutex_init_calloc_cb);
  1742 int
  1743 _pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex,
  1744     void *(calloc_cb)(size_t, size_t))
  1747 	return (0);
  1750 static bool
  1751 malloc_spin_init(pthread_mutex_t *lock)
  1754 	if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0)
  1755 		return (true);
  1757 	return (false);
  1760 static inline unsigned
  1761 malloc_spin_lock(pthread_mutex_t *lock)
  1763 	unsigned ret = 0;
  1765 	if (isthreaded) {
  1766 		if (_pthread_mutex_trylock(lock) != 0) {
  1767 			unsigned i;
  1768 			volatile unsigned j;
  1770 			/* Exponentially back off. */
  1771 			for (i = 1; i <= SPIN_LIMIT_2POW; i++) {
  1772 				for (j = 0; j < (1U << i); j++)
  1773 					ret++;
  1775 				CPU_SPINWAIT;
  1776 				if (_pthread_mutex_trylock(lock) == 0)
  1777 					return (ret);
  1780 			/*
  1781 			 * Spinning failed.  Block until the lock becomes
  1782 			 * available, in order to avoid indefinite priority
  1783 			 * inversion.
  1784 			 */
  1785 			_pthread_mutex_lock(lock);
  1786 			assert((ret << BLOCK_COST_2POW) != 0);
  1787 			return (ret << BLOCK_COST_2POW);
  1791 	return (ret);
  1794 static inline void
  1795 malloc_spin_unlock(pthread_mutex_t *lock)
  1798 	if (isthreaded)
  1799 		_pthread_mutex_unlock(lock);
  1801 #endif
  1803 /*
  1804  * End spin lock.
  1805  */
  1806 /******************************************************************************/
  1807 /*
  1808  * Begin Utility functions/macros.
  1809  */
  1811 /* Return the chunk address for allocation address a. */
  1812 #define	CHUNK_ADDR2BASE(a)						\
  1813 	((void *)((uintptr_t)(a) & ~chunksize_mask))
  1815 /* Return the chunk offset of address a. */
  1816 #define	CHUNK_ADDR2OFFSET(a)						\
  1817 	((size_t)((uintptr_t)(a) & chunksize_mask))
  1819 /* Return the smallest chunk multiple that is >= s. */
  1820 #define	CHUNK_CEILING(s)						\
  1821 	(((s) + chunksize_mask) & ~chunksize_mask)
  1823 /* Return the smallest cacheline multiple that is >= s. */
  1824 #define	CACHELINE_CEILING(s)						\
  1825 	(((s) + (CACHELINE - 1)) & ~(CACHELINE - 1))
  1827 /* Return the smallest quantum multiple that is >= a. */
  1828 #define	QUANTUM_CEILING(a)						\
  1829 	(((a) + quantum_mask) & ~quantum_mask)
  1831 /* Return the smallest pagesize multiple that is >= s. */
  1832 #define	PAGE_CEILING(s)							\
  1833 	(((s) + pagesize_mask) & ~pagesize_mask)
  1835 /* Compute the smallest power of 2 that is >= x. */
  1836 static inline size_t
  1837 pow2_ceil(size_t x)
  1840 	x--;
  1841 	x |= x >> 1;
  1842 	x |= x >> 2;
  1843 	x |= x >> 4;
  1844 	x |= x >> 8;
  1845 	x |= x >> 16;
  1846 #if (SIZEOF_PTR == 8)
  1847 	x |= x >> 32;
  1848 #endif
  1849 	x++;
  1850 	return (x);
  1853 #ifdef MALLOC_BALANCE
  1854 /*
  1855  * Use a simple linear congruential pseudo-random number generator:
  1857  *   prn(y) = (a*x + c) % m
  1859  * where the following constants ensure maximal period:
  1861  *   a == Odd number (relatively prime to 2^n), and (a-1) is a multiple of 4.
  1862  *   c == Odd number (relatively prime to 2^n).
  1863  *   m == 2^32
  1865  * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.
  1867  * This choice of m has the disadvantage that the quality of the bits is
  1868  * proportional to bit position.  For example. the lowest bit has a cycle of 2,
  1869  * the next has a cycle of 4, etc.  For this reason, we prefer to use the upper
  1870  * bits.
  1871  */
  1872 #  define PRN_DEFINE(suffix, var, a, c)					\
  1873 static inline void							\
  1874 sprn_##suffix(uint32_t seed)						\
  1875 {									\
  1876 	var = seed;							\
  1877 }									\
  1879 static inline uint32_t							\
  1880 prn_##suffix(uint32_t lg_range)						\
  1881 {									\
  1882 	uint32_t ret, x;						\
  1884 	assert(lg_range > 0);						\
  1885 	assert(lg_range <= 32);						\
  1887 	x = (var * (a)) + (c);						\
  1888 	var = x;							\
  1889 	ret = x >> (32 - lg_range);					\
  1891 	return (ret);							\
  1893 #  define SPRN(suffix, seed)	sprn_##suffix(seed)
  1894 #  define PRN(suffix, lg_range)	prn_##suffix(lg_range)
  1895 #endif
  1897 #ifdef MALLOC_BALANCE
  1898 /* Define the PRNG used for arena assignment. */
  1899 static __thread uint32_t balance_x;
  1900 PRN_DEFINE(balance, balance_x, 1297, 1301)
  1901 #endif
  1903 #ifdef MALLOC_UTRACE
  1904 static int
  1905 utrace(const void *addr, size_t len)
  1907 	malloc_utrace_t *ut = (malloc_utrace_t *)addr;
  1908 	char buf_a[UMAX2S_BUFSIZE];
  1909 	char buf_b[UMAX2S_BUFSIZE];
  1911 	assert(len == sizeof(malloc_utrace_t));
  1913 	if (ut->p == NULL && ut->s == 0 && ut->r == NULL) {
  1914 		_malloc_message(
  1915 		    umax2s(getpid(), 10, buf_a),
  1916 		    " x USER malloc_init()\n", "", "");
  1917 	} else if (ut->p == NULL && ut->r != NULL) {
  1918 		_malloc_message(
  1919 		    umax2s(getpid(), 10, buf_a),
  1920 		    " x USER 0x",
  1921 		    umax2s((uintptr_t)ut->r, 16, buf_b),
  1922 		    " = malloc(");
  1923 		_malloc_message(
  1924 		    umax2s(ut->s, 10, buf_a),
  1925 		    ")\n", "", "");
  1926 	} else if (ut->p != NULL && ut->r != NULL) {
  1927 		_malloc_message(
  1928 		    umax2s(getpid(), 10, buf_a),
  1929 		    " x USER 0x",
  1930 		    umax2s((uintptr_t)ut->r, 16, buf_b),
  1931 		    " = realloc(0x");
  1932 		_malloc_message(
  1933 		    umax2s((uintptr_t)ut->p, 16, buf_a),
  1934 		    ", ",
  1935 		    umax2s(ut->s, 10, buf_b),
  1936 		    ")\n");
  1937 	} else {
  1938 		_malloc_message(
  1939 		    umax2s(getpid(), 10, buf_a),
  1940 		    " x USER free(0x",
  1941 		    umax2s((uintptr_t)ut->p, 16, buf_b),
  1942 		    ")\n");
  1945 	return (0);
  1947 #endif
  1949 static inline const char *
  1950 _getprogname(void)
  1953 	return ("<jemalloc>");
  1956 #ifdef MALLOC_STATS
  1957 /*
  1958  * Print to stderr in such a way as to (hopefully) avoid memory allocation.
  1959  */
  1960 static void
  1961 malloc_printf(const char *format, ...)
  1963 	char buf[4096];
  1964 	va_list ap;
  1966 	va_start(ap, format);
  1967 	vsnprintf(buf, sizeof(buf), format, ap);
  1968 	va_end(ap);
  1969 	_malloc_message(buf, "", "", "");
  1971 #endif
  1973 /******************************************************************************/
  1975 static inline void
  1976 pages_decommit(void *addr, size_t size)
  1979 #ifdef MOZ_MEMORY_WINDOWS
  1980 	VirtualFree(addr, size, MEM_DECOMMIT);
  1981 #else
  1982 	if (mmap(addr, size, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1,
  1983 	    0) == MAP_FAILED)
  1984 		abort();
  1985 #endif
  1988 static inline void
  1989 pages_commit(void *addr, size_t size)
  1992 #  ifdef MOZ_MEMORY_WINDOWS
  1993 	if (!VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE))
  1994 		abort();
  1995 #  else
  1996 	if (mmap(addr, size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE |
  1997 	    MAP_ANON, -1, 0) == MAP_FAILED)
  1998 		abort();
  1999 #  endif
  2002 static bool
  2003 base_pages_alloc_mmap(size_t minsize)
  2005 	bool ret;
  2006 	size_t csize;
  2007 #if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS)
  2008 	size_t pminsize;
  2009 #endif
  2010 	int pfd;
  2012 	assert(minsize != 0);
  2013 	csize = CHUNK_CEILING(minsize);
  2014 #ifdef MALLOC_PAGEFILE
  2015 	if (opt_pagefile) {
  2016 		pfd = pagefile_init(csize);
  2017 		if (pfd == -1)
  2018 			return (true);
  2019 	} else
  2020 #endif
  2021 		pfd = -1;
  2022 	base_pages = pages_map(NULL, csize, pfd);
  2023 	if (base_pages == NULL) {
  2024 		ret = true;
  2025 		goto RETURN;
  2027 	base_next_addr = base_pages;
  2028 	base_past_addr = (void *)((uintptr_t)base_pages + csize);
  2029 #if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS)
  2030 	/*
  2031 	 * Leave enough pages for minsize committed, since otherwise they would
  2032 	 * have to be immediately recommitted.
  2033 	 */
  2034 	pminsize = PAGE_CEILING(minsize);
  2035 	base_next_decommitted = (void *)((uintptr_t)base_pages + pminsize);
  2036 #  if defined(MALLOC_DECOMMIT)
  2037 	if (pminsize < csize)
  2038 		pages_decommit(base_next_decommitted, csize - pminsize);
  2039 #  endif
  2040 #  ifdef MALLOC_STATS
  2041 	base_mapped += csize;
  2042 	base_committed += pminsize;
  2043 #  endif
  2044 #endif
  2046 	ret = false;
  2047 RETURN:
  2048 #ifdef MALLOC_PAGEFILE
  2049 	if (pfd != -1)
  2050 		pagefile_close(pfd);
  2051 #endif
  2052 	return (false);
  2055 static bool
  2056 base_pages_alloc(size_t minsize)
  2059 	if (base_pages_alloc_mmap(minsize) == false)
  2060 		return (false);
  2062 	return (true);
  2065 static void *
  2066 base_alloc(size_t size)
  2068 	void *ret;
  2069 	size_t csize;
  2071 	/* Round size up to nearest multiple of the cacheline size. */
  2072 	csize = CACHELINE_CEILING(size);
  2074 	malloc_mutex_lock(&base_mtx);
  2075 	/* Make sure there's enough space for the allocation. */
  2076 	if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
  2077 		if (base_pages_alloc(csize)) {
  2078 			malloc_mutex_unlock(&base_mtx);
  2079 			return (NULL);
  2082 	/* Allocate. */
  2083 	ret = base_next_addr;
  2084 	base_next_addr = (void *)((uintptr_t)base_next_addr + csize);
  2085 #if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS)
  2086 	/* Make sure enough pages are committed for the new allocation. */
  2087 	if ((uintptr_t)base_next_addr > (uintptr_t)base_next_decommitted) {
  2088 		void *pbase_next_addr =
  2089 		    (void *)(PAGE_CEILING((uintptr_t)base_next_addr));
  2091 #  ifdef MALLOC_DECOMMIT
  2092 		pages_commit(base_next_decommitted, (uintptr_t)pbase_next_addr -
  2093 		    (uintptr_t)base_next_decommitted);
  2094 #  endif
  2095 		base_next_decommitted = pbase_next_addr;
  2096 #  ifdef MALLOC_STATS
  2097 		base_committed += (uintptr_t)pbase_next_addr -
  2098 		    (uintptr_t)base_next_decommitted;
  2099 #  endif
  2101 #endif
  2102 	malloc_mutex_unlock(&base_mtx);
  2103 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
  2105 	return (ret);
  2108 static void *
  2109 base_calloc(size_t number, size_t size)
  2111 	void *ret;
  2113 	ret = base_alloc(number * size);
  2114 #ifdef MALLOC_VALGRIND
  2115 	if (ret != NULL) {
  2116 		VALGRIND_FREELIKE_BLOCK(ret, 0);
  2117 		VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, true);
  2119 #endif
  2120 	memset(ret, 0, number * size);
  2122 	return (ret);
  2125 static extent_node_t *
  2126 base_node_alloc(void)
  2128 	extent_node_t *ret;
  2130 	malloc_mutex_lock(&base_mtx);
  2131 	if (base_nodes != NULL) {
  2132 		ret = base_nodes;
  2133 		base_nodes = *(extent_node_t **)ret;
  2134 		VALGRIND_FREELIKE_BLOCK(ret, 0);
  2135 		VALGRIND_MALLOCLIKE_BLOCK(ret, sizeof(extent_node_t), 0, false);
  2136 		malloc_mutex_unlock(&base_mtx);
  2137 	} else {
  2138 		malloc_mutex_unlock(&base_mtx);
  2139 		ret = (extent_node_t *)base_alloc(sizeof(extent_node_t));
  2142 	return (ret);
  2145 static void
  2146 base_node_dealloc(extent_node_t *node)
  2149 	malloc_mutex_lock(&base_mtx);
  2150 	VALGRIND_FREELIKE_BLOCK(node, 0);
  2151 	VALGRIND_MALLOCLIKE_BLOCK(node, sizeof(extent_node_t *), 0, false);
  2152 	*(extent_node_t **)node = base_nodes;
  2153 	base_nodes = node;
  2154 	malloc_mutex_unlock(&base_mtx);
  2157 /******************************************************************************/
  2159 #ifdef MALLOC_STATS
  2160 static void
  2161 stats_print(arena_t *arena)
  2163 	unsigned i, gap_start;
  2165 #ifdef MOZ_MEMORY_WINDOWS
  2166 	malloc_printf("dirty: %Iu page%s dirty, %I64u sweep%s,"
  2167 	    " %I64u madvise%s, %I64u page%s purged\n",
  2168 	    arena->ndirty, arena->ndirty == 1 ? "" : "s",
  2169 	    arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s",
  2170 	    arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s",
  2171 	    arena->stats.purged, arena->stats.purged == 1 ? "" : "s");
  2172 #  ifdef MALLOC_DECOMMIT
  2173 	malloc_printf("decommit: %I64u decommit%s, %I64u commit%s,"
  2174 	    " %I64u page%s decommitted\n",
  2175 	    arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s",
  2176 	    arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s",
  2177 	    arena->stats.decommitted,
  2178 	    (arena->stats.decommitted == 1) ? "" : "s");
  2179 #  endif
  2181 	malloc_printf("            allocated      nmalloc      ndalloc\n");
  2182 	malloc_printf("small:   %12Iu %12I64u %12I64u\n",
  2183 	    arena->stats.allocated_small, arena->stats.nmalloc_small,
  2184 	    arena->stats.ndalloc_small);
  2185 	malloc_printf("large:   %12Iu %12I64u %12I64u\n",
  2186 	    arena->stats.allocated_large, arena->stats.nmalloc_large,
  2187 	    arena->stats.ndalloc_large);
  2188 	malloc_printf("total:   %12Iu %12I64u %12I64u\n",
  2189 	    arena->stats.allocated_small + arena->stats.allocated_large,
  2190 	    arena->stats.nmalloc_small + arena->stats.nmalloc_large,
  2191 	    arena->stats.ndalloc_small + arena->stats.ndalloc_large);
  2192 	malloc_printf("mapped:  %12Iu\n", arena->stats.mapped);
  2193 #else
  2194 	malloc_printf("dirty: %zu page%s dirty, %llu sweep%s,"
  2195 	    " %llu madvise%s, %llu page%s purged\n",
  2196 	    arena->ndirty, arena->ndirty == 1 ? "" : "s",
  2197 	    arena->stats.npurge, arena->stats.npurge == 1 ? "" : "s",
  2198 	    arena->stats.nmadvise, arena->stats.nmadvise == 1 ? "" : "s",
  2199 	    arena->stats.purged, arena->stats.purged == 1 ? "" : "s");
  2200 #  ifdef MALLOC_DECOMMIT
  2201 	malloc_printf("decommit: %llu decommit%s, %llu commit%s,"
  2202 	    " %llu page%s decommitted\n",
  2203 	    arena->stats.ndecommit, (arena->stats.ndecommit == 1) ? "" : "s",
  2204 	    arena->stats.ncommit, (arena->stats.ncommit == 1) ? "" : "s",
  2205 	    arena->stats.decommitted,
  2206 	    (arena->stats.decommitted == 1) ? "" : "s");
  2207 #  endif
  2209 	malloc_printf("            allocated      nmalloc      ndalloc\n");
  2210 	malloc_printf("small:   %12zu %12llu %12llu\n",
  2211 	    arena->stats.allocated_small, arena->stats.nmalloc_small,
  2212 	    arena->stats.ndalloc_small);
  2213 	malloc_printf("large:   %12zu %12llu %12llu\n",
  2214 	    arena->stats.allocated_large, arena->stats.nmalloc_large,
  2215 	    arena->stats.ndalloc_large);
  2216 	malloc_printf("total:   %12zu %12llu %12llu\n",
  2217 	    arena->stats.allocated_small + arena->stats.allocated_large,
  2218 	    arena->stats.nmalloc_small + arena->stats.nmalloc_large,
  2219 	    arena->stats.ndalloc_small + arena->stats.ndalloc_large);
  2220 	malloc_printf("mapped:  %12zu\n", arena->stats.mapped);
  2221 #endif
  2222 	malloc_printf("bins:     bin   size regs pgs  requests   newruns"
  2223 	    "    reruns maxruns curruns\n");
  2224 	for (i = 0, gap_start = UINT_MAX; i < ntbins + nqbins + nsbins; i++) {
  2225 		if (arena->bins[i].stats.nrequests == 0) {
  2226 			if (gap_start == UINT_MAX)
  2227 				gap_start = i;
  2228 		} else {
  2229 			if (gap_start != UINT_MAX) {
  2230 				if (i > gap_start + 1) {
  2231 					/* Gap of more than one size class. */
  2232 					malloc_printf("[%u..%u]\n",
  2233 					    gap_start, i - 1);
  2234 				} else {
  2235 					/* Gap of one size class. */
  2236 					malloc_printf("[%u]\n", gap_start);
  2238 				gap_start = UINT_MAX;
  2240 			malloc_printf(
  2241 #if defined(MOZ_MEMORY_WINDOWS)
  2242 			    "%13u %1s %4u %4u %3u %9I64u %9I64u"
  2243 			    " %9I64u %7u %7u\n",
  2244 #else
  2245 			    "%13u %1s %4u %4u %3u %9llu %9llu"
  2246 			    " %9llu %7lu %7lu\n",
  2247 #endif
  2248 			    i,
  2249 			    i < ntbins ? "T" : i < ntbins + nqbins ? "Q" : "S",
  2250 			    arena->bins[i].reg_size,
  2251 			    arena->bins[i].nregs,
  2252 			    arena->bins[i].run_size >> pagesize_2pow,
  2253 			    arena->bins[i].stats.nrequests,
  2254 			    arena->bins[i].stats.nruns,
  2255 			    arena->bins[i].stats.reruns,
  2256 			    arena->bins[i].stats.highruns,
  2257 			    arena->bins[i].stats.curruns);
  2260 	if (gap_start != UINT_MAX) {
  2261 		if (i > gap_start + 1) {
  2262 			/* Gap of more than one size class. */
  2263 			malloc_printf("[%u..%u]\n", gap_start, i - 1);
  2264 		} else {
  2265 			/* Gap of one size class. */
  2266 			malloc_printf("[%u]\n", gap_start);
  2270 #endif
  2272 /*
  2273  * End Utility functions/macros.
  2274  */
  2275 /******************************************************************************/
  2276 /*
  2277  * Begin extent tree code.
  2278  */
  2280 static inline int
  2281 extent_szad_comp(extent_node_t *a, extent_node_t *b)
  2283 	int ret;
  2284 	size_t a_size = a->size;
  2285 	size_t b_size = b->size;
  2287 	ret = (a_size > b_size) - (a_size < b_size);
  2288 	if (ret == 0) {
  2289 		uintptr_t a_addr = (uintptr_t)a->addr;
  2290 		uintptr_t b_addr = (uintptr_t)b->addr;
  2292 		ret = (a_addr > b_addr) - (a_addr < b_addr);
  2295 	return (ret);
  2298 /* Wrap red-black tree macros in functions. */
  2299 rb_wrap(static, extent_tree_szad_, extent_tree_t, extent_node_t,
  2300     link_szad, extent_szad_comp)
  2302 static inline int
  2303 extent_ad_comp(extent_node_t *a, extent_node_t *b)
  2305 	uintptr_t a_addr = (uintptr_t)a->addr;
  2306 	uintptr_t b_addr = (uintptr_t)b->addr;
  2308 	return ((a_addr > b_addr) - (a_addr < b_addr));
  2311 /* Wrap red-black tree macros in functions. */
  2312 rb_wrap(static, extent_tree_ad_, extent_tree_t, extent_node_t, link_ad,
  2313     extent_ad_comp)
  2315 /*
  2316  * End extent tree code.
  2317  */
  2318 /******************************************************************************/
  2319 /*
  2320  * Begin chunk management functions.
  2321  */
  2323 #ifdef MOZ_MEMORY_WINDOWS
  2325 static void *
  2326 pages_map(void *addr, size_t size, int pfd)
  2328 	void *ret = NULL;
  2329 	ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,
  2330 	    PAGE_READWRITE);
  2331 	return (ret);
  2334 static void
  2335 pages_unmap(void *addr, size_t size)
  2337 	if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
  2338 		_malloc_message(_getprogname(),
  2339 		    ": (malloc) Error in VirtualFree()\n", "", "");
  2340 		if (opt_abort)
  2341 			abort();
  2344 #else
  2345 #ifdef JEMALLOC_USES_MAP_ALIGN
  2346 static void *
  2347 pages_map_align(size_t size, int pfd, size_t alignment)
  2349 	void *ret;
  2351 	/*
  2352 	 * We don't use MAP_FIXED here, because it can cause the *replacement*
  2353 	 * of existing mappings, and we only want to create new mappings.
  2354 	 */
  2355 #ifdef MALLOC_PAGEFILE
  2356 	if (pfd != -1) {
  2357 		ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
  2358 		    MAP_NOSYNC | MAP_ALIGN, pfd, 0);
  2359 	} else
  2360 #endif
  2362 		ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
  2363 		    MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0);
  2365 	assert(ret != NULL);
  2367 	if (ret == MAP_FAILED)
  2368 		ret = NULL;
  2369 	return (ret);
  2371 #endif
  2373 static void *
  2374 pages_map(void *addr, size_t size, int pfd)
  2376 	void *ret;
  2377 #if defined(__ia64__)
  2378         /*
  2379          * The JS engine assumes that all allocated pointers have their high 17 bits clear,
  2380          * which ia64's mmap doesn't support directly. However, we can emulate it by passing
  2381          * mmap an "addr" parameter with those bits clear. The mmap will return that address,
  2382          * or the nearest available memory above that address, providing a near-guarantee
  2383          * that those bits are clear. If they are not, we return NULL below to indicate
  2384          * out-of-memory.
  2386          * The addr is chosen as 0x0000070000000000, which still allows about 120TB of virtual 
  2387          * address space.
  2389          * See Bug 589735 for more information.
  2390          */
  2391 	bool check_placement = true;
  2392         if (addr == NULL) {
  2393 		addr = (void*)0x0000070000000000;
  2394 		check_placement = false;
  2396 #endif
  2398 	/*
  2399 	 * We don't use MAP_FIXED here, because it can cause the *replacement*
  2400 	 * of existing mappings, and we only want to create new mappings.
  2401 	 */
  2402 #ifdef MALLOC_PAGEFILE
  2403 	if (pfd != -1) {
  2404 		ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
  2405 		    MAP_NOSYNC, pfd, 0);
  2406 	} else
  2407 #endif
  2409 		ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
  2410 		    MAP_ANON, -1, 0);
  2412 	assert(ret != NULL);
  2414 	if (ret == MAP_FAILED) {
  2415 		ret = NULL;
  2417 #if defined(__ia64__)
  2418         /* 
  2419          * If the allocated memory doesn't have its upper 17 bits clear, consider it 
  2420          * as out of memory.
  2421         */
  2422         else if ((long long)ret & 0xffff800000000000) {
  2423 		munmap(ret, size);
  2424                 ret = NULL;
  2426         /* If the caller requested a specific memory location, verify that's what mmap returned. */
  2427 	else if (check_placement && ret != addr) {
  2428 #else
  2429 	else if (addr != NULL && ret != addr) {
  2430 #endif
  2431 		/*
  2432 		 * We succeeded in mapping memory, but not in the right place.
  2433 		 */
  2434 		if (munmap(ret, size) == -1) {
  2435 			char buf[STRERROR_BUF];
  2437 			strerror_r(errno, buf, sizeof(buf));
  2438 			_malloc_message(_getprogname(),
  2439 			    ": (malloc) Error in munmap(): ", buf, "\n");
  2440 			if (opt_abort)
  2441 				abort();
  2443 		ret = NULL;
  2446 #if defined(__ia64__)
  2447 	assert(ret == NULL || (!check_placement && ret != NULL)
  2448 	    || (check_placement && ret == addr));
  2449 #else
  2450 	assert(ret == NULL || (addr == NULL && ret != addr)
  2451 	    || (addr != NULL && ret == addr));
  2452 #endif
  2453 	return (ret);
  2456 static void
  2457 pages_unmap(void *addr, size_t size)
  2460 	if (munmap(addr, size) == -1) {
  2461 		char buf[STRERROR_BUF];
  2463 		strerror_r(errno, buf, sizeof(buf));
  2464 		_malloc_message(_getprogname(),
  2465 		    ": (malloc) Error in munmap(): ", buf, "\n");
  2466 		if (opt_abort)
  2467 			abort();
  2470 #endif
  2472 #ifdef MOZ_MEMORY_DARWIN
  2473 #define	VM_COPY_MIN (pagesize << 5)
  2474 static inline void
  2475 pages_copy(void *dest, const void *src, size_t n)
  2478 	assert((void *)((uintptr_t)dest & ~pagesize_mask) == dest);
  2479 	assert(n >= VM_COPY_MIN);
  2480 	assert((void *)((uintptr_t)src & ~pagesize_mask) == src);
  2482 	vm_copy(mach_task_self(), (vm_address_t)src, (vm_size_t)n,
  2483 	    (vm_address_t)dest);
  2485 #endif
  2487 #ifdef MALLOC_VALIDATE
  2488 static inline malloc_rtree_t *
  2489 malloc_rtree_new(unsigned bits)
  2491 	malloc_rtree_t *ret;
  2492 	unsigned bits_per_level, height, i;
  2494 	bits_per_level = ffs(pow2_ceil((MALLOC_RTREE_NODESIZE /
  2495 	    sizeof(void *)))) - 1;
  2496 	height = bits / bits_per_level;
  2497 	if (height * bits_per_level != bits)
  2498 		height++;
  2499 	RELEASE_ASSERT(height * bits_per_level >= bits);
  2501 	ret = (malloc_rtree_t*)base_calloc(1, sizeof(malloc_rtree_t) +
  2502 	    (sizeof(unsigned) * (height - 1)));
  2503 	if (ret == NULL)
  2504 		return (NULL);
  2506 	malloc_spin_init(&ret->lock);
  2507 	ret->height = height;
  2508 	if (bits_per_level * height > bits)
  2509 		ret->level2bits[0] = bits % bits_per_level;
  2510 	else
  2511 		ret->level2bits[0] = bits_per_level;
  2512 	for (i = 1; i < height; i++)
  2513 		ret->level2bits[i] = bits_per_level;
  2515 	ret->root = (void**)base_calloc(1, sizeof(void *) << ret->level2bits[0]);
  2516 	if (ret->root == NULL) {
  2517 		/*
  2518 		 * We leak the rtree here, since there's no generic base
  2519 		 * deallocation.
  2520 		 */
  2521 		return (NULL);
  2524 	return (ret);
  2527 #define	MALLOC_RTREE_GET_GENERATE(f)					\
  2528 /* The least significant bits of the key are ignored. */		\
  2529 static inline void *							\
  2530 f(malloc_rtree_t *rtree, uintptr_t key)					\
  2531 {									\
  2532 	void *ret;							\
  2533 	uintptr_t subkey;						\
  2534 	unsigned i, lshift, height, bits;				\
  2535 	void **node, **child;						\
  2537 	MALLOC_RTREE_LOCK(&rtree->lock);				\
  2538 	for (i = lshift = 0, height = rtree->height, node = rtree->root;\
  2539 	    i < height - 1;						\
  2540 	    i++, lshift += bits, node = child) {			\
  2541 		bits = rtree->level2bits[i];				\
  2542 		subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);	\
  2543 		child = (void**)node[subkey];				\
  2544 		if (child == NULL) {					\
  2545 			MALLOC_RTREE_UNLOCK(&rtree->lock);		\
  2546 			return (NULL);					\
  2547 		}							\
  2548 	}								\
  2550 	/*								\
  2551 	 * node is a leaf, so it contains values rather than node	\
  2552 	 * pointers.							\
  2553 	 */								\
  2554 	bits = rtree->level2bits[i];					\
  2555 	subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);		\
  2556 	ret = node[subkey];						\
  2557 	MALLOC_RTREE_UNLOCK(&rtree->lock);				\
  2559 	MALLOC_RTREE_GET_VALIDATE					\
  2560 	return (ret);							\
  2563 #ifdef MALLOC_DEBUG
  2564 #  define MALLOC_RTREE_LOCK(l)		malloc_spin_lock(l)
  2565 #  define MALLOC_RTREE_UNLOCK(l)	malloc_spin_unlock(l)
  2566 #  define MALLOC_RTREE_GET_VALIDATE
  2567 MALLOC_RTREE_GET_GENERATE(malloc_rtree_get_locked)
  2568 #  undef MALLOC_RTREE_LOCK
  2569 #  undef MALLOC_RTREE_UNLOCK
  2570 #  undef MALLOC_RTREE_GET_VALIDATE
  2571 #endif
  2573 #define	MALLOC_RTREE_LOCK(l)
  2574 #define	MALLOC_RTREE_UNLOCK(l)
  2575 #ifdef MALLOC_DEBUG
  2576    /*
  2577     * Suppose that it were possible for a jemalloc-allocated chunk to be
  2578     * munmap()ped, followed by a different allocator in another thread re-using
  2579     * overlapping virtual memory, all without invalidating the cached rtree
  2580     * value.  The result would be a false positive (the rtree would claim that
  2581     * jemalloc owns memory that it had actually discarded).  I don't think this
  2582     * scenario is possible, but the following assertion is a prudent sanity
  2583     * check.
  2584     */
  2585 #  define MALLOC_RTREE_GET_VALIDATE					\
  2586 	assert(malloc_rtree_get_locked(rtree, key) == ret);
  2587 #else
  2588 #  define MALLOC_RTREE_GET_VALIDATE
  2589 #endif
  2590 MALLOC_RTREE_GET_GENERATE(malloc_rtree_get)
  2591 #undef MALLOC_RTREE_LOCK
  2592 #undef MALLOC_RTREE_UNLOCK
  2593 #undef MALLOC_RTREE_GET_VALIDATE
  2595 static inline bool
  2596 malloc_rtree_set(malloc_rtree_t *rtree, uintptr_t key, void *val)
  2598 	uintptr_t subkey;
  2599 	unsigned i, lshift, height, bits;
  2600 	void **node, **child;
  2602 	malloc_spin_lock(&rtree->lock);
  2603 	for (i = lshift = 0, height = rtree->height, node = rtree->root;
  2604 	    i < height - 1;
  2605 	    i++, lshift += bits, node = child) {
  2606 		bits = rtree->level2bits[i];
  2607 		subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
  2608 		child = (void**)node[subkey];
  2609 		if (child == NULL) {
  2610 			child = (void**)base_calloc(1, sizeof(void *) <<
  2611 			    rtree->level2bits[i+1]);
  2612 			if (child == NULL) {
  2613 				malloc_spin_unlock(&rtree->lock);
  2614 				return (true);
  2616 			node[subkey] = child;
  2620 	/* node is a leaf, so it contains values rather than node pointers. */
  2621 	bits = rtree->level2bits[i];
  2622 	subkey = (key << lshift) >> ((SIZEOF_PTR << 3) - bits);
  2623 	node[subkey] = val;
  2624 	malloc_spin_unlock(&rtree->lock);
  2626 	return (false);
  2628 #endif
  2630 #if defined(MOZ_MEMORY_WINDOWS) || defined(JEMALLOC_USES_MAP_ALIGN) || defined(MALLOC_PAGEFILE)
  2632 /* Allocate an aligned chunk while maintaining a 1:1 correspondence between
  2633  * mmap and unmap calls.  This is important on Windows, but not elsewhere. */
  2634 static void *
  2635 chunk_alloc_mmap(size_t size, bool pagefile)
  2637 	void *ret;
  2638 #ifndef JEMALLOC_USES_MAP_ALIGN
  2639 	size_t offset;
  2640 #endif
  2641 	int pfd;
  2643 #ifdef MALLOC_PAGEFILE
  2644 	if (opt_pagefile && pagefile) {
  2645 		pfd = pagefile_init(size);
  2646 		if (pfd == -1)
  2647 			return (NULL);
  2648 	} else
  2649 #endif
  2650 		pfd = -1;
  2652 #ifdef JEMALLOC_USES_MAP_ALIGN
  2653 	ret = pages_map_align(size, pfd, chunksize);
  2654 #else
  2655 	ret = pages_map(NULL, size, pfd);
  2656 	if (ret == NULL)
  2657 		goto RETURN;
  2659 	offset = CHUNK_ADDR2OFFSET(ret);
  2660 	if (offset != 0) {
  2661 		/* Deallocate, then try to allocate at (ret + size - offset). */
  2662 		pages_unmap(ret, size);
  2663 		ret = pages_map((void *)((uintptr_t)ret + size - offset), size,
  2664 		    pfd);
  2665 		while (ret == NULL) {
  2666 			/*
  2667 			 * Over-allocate in order to map a memory region that
  2668 			 * is definitely large enough.
  2669 			 */
  2670 			ret = pages_map(NULL, size + chunksize, -1);
  2671 			if (ret == NULL)
  2672 				goto RETURN;
  2673 			/*
  2674 			 * Deallocate, then allocate the correct size, within
  2675 			 * the over-sized mapping.
  2676 			 */
  2677 			offset = CHUNK_ADDR2OFFSET(ret);
  2678 			pages_unmap(ret, size + chunksize);
  2679 			if (offset == 0)
  2680 				ret = pages_map(ret, size, pfd);
  2681 			else {
  2682 				ret = pages_map((void *)((uintptr_t)ret +
  2683 				    chunksize - offset), size, pfd);
  2685 			/*
  2686 			 * Failure here indicates a race with another thread, so
  2687 			 * try again.
  2688 			 */
  2691 RETURN:
  2692 #endif
  2693 #ifdef MALLOC_PAGEFILE
  2694 	if (pfd != -1)
  2695 		pagefile_close(pfd);
  2696 #endif
  2698 	return (ret);
  2701 #else /* ! (defined(MOZ_MEMORY_WINDOWS) || defined(JEMALLOC_USES_MAP_ALIGN) || defined(MALLOC_PAGEFILE)) */
  2703 /* pages_trim, chunk_alloc_mmap_slow and chunk_alloc_mmap were cherry-picked
  2704  * from upstream jemalloc 3.4.1 to fix Mozilla bug 956501. */
  2706 /* Return the offset between a and the nearest aligned address at or below a. */
  2707 #define        ALIGNMENT_ADDR2OFFSET(a, alignment)                                \
  2708         ((size_t)((uintptr_t)(a) & (alignment - 1)))
  2710 /* Return the smallest alignment multiple that is >= s. */
  2711 #define        ALIGNMENT_CEILING(s, alignment)                                        \
  2712         (((s) + (alignment - 1)) & (-(alignment)))
  2714 static void *
  2715 pages_trim(void *addr, size_t alloc_size, size_t leadsize, size_t size)
  2717         size_t trailsize;
  2718         void *ret = (void *)((uintptr_t)addr + leadsize);
  2720         assert(alloc_size >= leadsize + size);
  2721         trailsize = alloc_size - leadsize - size;
  2723         if (leadsize != 0)
  2724                 pages_unmap(addr, leadsize);
  2725         if (trailsize != 0)
  2726                 pages_unmap((void *)((uintptr_t)ret + size), trailsize);
  2727         return (ret);
  2730 static void *
  2731 chunk_alloc_mmap_slow(size_t size, size_t alignment)
  2733         void *ret, *pages;
  2734         size_t alloc_size, leadsize;
  2736         alloc_size = size + alignment - pagesize;
  2737         /* Beware size_t wrap-around. */
  2738         if (alloc_size < size)
  2739                 return (NULL);
  2740         do {
  2741                 pages = pages_map(NULL, alloc_size, -1);
  2742                 if (pages == NULL)
  2743                         return (NULL);
  2744                 leadsize = ALIGNMENT_CEILING((uintptr_t)pages, alignment) -
  2745                         (uintptr_t)pages;
  2746                 ret = pages_trim(pages, alloc_size, leadsize, size);
  2747         } while (ret == NULL);
  2749         assert(ret != NULL);
  2750         return (ret);
  2753 static void *
  2754 chunk_alloc_mmap(size_t size, bool pagefile)
  2756         void *ret;
  2757         size_t offset;
  2759         /*
  2760          * Ideally, there would be a way to specify alignment to mmap() (like
  2761          * NetBSD has), but in the absence of such a feature, we have to work
  2762          * hard to efficiently create aligned mappings. The reliable, but
  2763          * slow method is to create a mapping that is over-sized, then trim the
  2764          * excess. However, that always results in one or two calls to
  2765          * pages_unmap().
  2767          * Optimistically try mapping precisely the right amount before falling
  2768          * back to the slow method, with the expectation that the optimistic
  2769          * approach works most of the time.
  2770          */
  2772         ret = pages_map(NULL, size, -1);
  2773         if (ret == NULL)
  2774                 return (NULL);
  2775         offset = ALIGNMENT_ADDR2OFFSET(ret, chunksize);
  2776         if (offset != 0) {
  2777                 pages_unmap(ret, size);
  2778                 return (chunk_alloc_mmap_slow(size, chunksize));
  2781         assert(ret != NULL);
  2782         return (ret);
  2785 #endif /* defined(MOZ_MEMORY_WINDOWS) || defined(JEMALLOC_USES_MAP_ALIGN) || defined(MALLOC_PAGEFILE) */
  2787 #ifdef MALLOC_PAGEFILE
  2788 static int
  2789 pagefile_init(size_t size)
  2791 	int ret;
  2792 	size_t i;
  2793 	char pagefile_path[PATH_MAX];
  2794 	char zbuf[MALLOC_PAGEFILE_WRITE_SIZE];
  2796 	/*
  2797 	 * Create a temporary file, then immediately unlink it so that it will
  2798 	 * not persist.
  2799 	 */
  2800 	strcpy(pagefile_path, pagefile_templ);
  2801 	ret = mkstemp(pagefile_path);
  2802 	if (ret == -1)
  2803 		return (ret);
  2804 	if (unlink(pagefile_path)) {
  2805 		char buf[STRERROR_BUF];
  2807 		strerror_r(errno, buf, sizeof(buf));
  2808 		_malloc_message(_getprogname(), ": (malloc) Error in unlink(\"",
  2809 		    pagefile_path, "\"):");
  2810 		_malloc_message(buf, "\n", "", "");
  2811 		if (opt_abort)
  2812 			abort();
  2815 	/*
  2816 	 * Write sequential zeroes to the file in order to assure that disk
  2817 	 * space is committed, with minimal fragmentation.  It would be
  2818 	 * sufficient to write one zero per disk block, but that potentially
  2819 	 * results in more system calls, for no real gain.
  2820 	 */
  2821 	memset(zbuf, 0, sizeof(zbuf));
  2822 	for (i = 0; i < size; i += sizeof(zbuf)) {
  2823 		if (write(ret, zbuf, sizeof(zbuf)) != sizeof(zbuf)) {
  2824 			if (errno != ENOSPC) {
  2825 				char buf[STRERROR_BUF];
  2827 				strerror_r(errno, buf, sizeof(buf));
  2828 				_malloc_message(_getprogname(),
  2829 				    ": (malloc) Error in write(): ", buf, "\n");
  2830 				if (opt_abort)
  2831 					abort();
  2833 			pagefile_close(ret);
  2834 			return (-1);
  2838 	return (ret);
  2841 static void
  2842 pagefile_close(int pfd)
  2845 	if (close(pfd)) {
  2846 		char buf[STRERROR_BUF];
  2848 		strerror_r(errno, buf, sizeof(buf));
  2849 		_malloc_message(_getprogname(),
  2850 		    ": (malloc) Error in close(): ", buf, "\n");
  2851 		if (opt_abort)
  2852 			abort();
  2855 #endif
  2857 static void *
  2858 chunk_alloc(size_t size, bool zero, bool pagefile)
  2860 	void *ret;
  2862 	assert(size != 0);
  2863 	assert((size & chunksize_mask) == 0);
  2865 	ret = chunk_alloc_mmap(size, pagefile);
  2866 	if (ret != NULL) {
  2867 		goto RETURN;
  2870 	/* All strategies for allocation failed. */
  2871 	ret = NULL;
  2872 RETURN:
  2874 #ifdef MALLOC_VALIDATE
  2875 	if (ret != NULL) {
  2876 		if (malloc_rtree_set(chunk_rtree, (uintptr_t)ret, ret)) {
  2877 			chunk_dealloc(ret, size);
  2878 			return (NULL);
  2881 #endif
  2883 	assert(CHUNK_ADDR2BASE(ret) == ret);
  2884 	return (ret);
  2887 static void
  2888 chunk_dealloc_mmap(void *chunk, size_t size)
  2891 	pages_unmap(chunk, size);
  2894 static void
  2895 chunk_dealloc(void *chunk, size_t size)
  2898 	assert(chunk != NULL);
  2899 	assert(CHUNK_ADDR2BASE(chunk) == chunk);
  2900 	assert(size != 0);
  2901 	assert((size & chunksize_mask) == 0);
  2903 #ifdef MALLOC_VALIDATE
  2904 	malloc_rtree_set(chunk_rtree, (uintptr_t)chunk, NULL);
  2905 #endif
  2907 	chunk_dealloc_mmap(chunk, size);
  2910 /*
  2911  * End chunk management functions.
  2912  */
  2913 /******************************************************************************/
  2914 /*
  2915  * Begin arena.
  2916  */
  2918 /*
  2919  * Choose an arena based on a per-thread value (fast-path code, calls slow-path
  2920  * code if necessary).
  2921  */
  2922 static inline arena_t *
  2923 choose_arena(void)
  2925 	arena_t *ret;
  2927 	/*
  2928 	 * We can only use TLS if this is a PIC library, since for the static
  2929 	 * library version, libc's malloc is used by TLS allocation, which
  2930 	 * introduces a bootstrapping issue.
  2931 	 */
  2932 #ifndef NO_TLS
  2933 	if (isthreaded == false) {
  2934 	    /* Avoid the overhead of TLS for single-threaded operation. */
  2935 	    return (arenas[0]);
  2938 #  ifdef MOZ_MEMORY_WINDOWS
  2939 	ret = (arena_t*)TlsGetValue(tlsIndex);
  2940 #  else
  2941 	ret = arenas_map;
  2942 #  endif
  2944 	if (ret == NULL) {
  2945 		ret = choose_arena_hard();
  2946 		RELEASE_ASSERT(ret != NULL);
  2948 #else
  2949 	if (isthreaded && narenas > 1) {
  2950 		unsigned long ind;
  2952 		/*
  2953 		 * Hash _pthread_self() to one of the arenas.  There is a prime
  2954 		 * number of arenas, so this has a reasonable chance of
  2955 		 * working.  Even so, the hashing can be easily thwarted by
  2956 		 * inconvenient _pthread_self() values.  Without specific
  2957 		 * knowledge of how _pthread_self() calculates values, we can't
  2958 		 * easily do much better than this.
  2959 		 */
  2960 		ind = (unsigned long) _pthread_self() % narenas;
  2962 		/*
  2963 		 * Optimistially assume that arenas[ind] has been initialized.
  2964 		 * At worst, we find out that some other thread has already
  2965 		 * done so, after acquiring the lock in preparation.  Note that
  2966 		 * this lazy locking also has the effect of lazily forcing
  2967 		 * cache coherency; without the lock acquisition, there's no
  2968 		 * guarantee that modification of arenas[ind] by another thread
  2969 		 * would be seen on this CPU for an arbitrary amount of time.
  2971 		 * In general, this approach to modifying a synchronized value
  2972 		 * isn't a good idea, but in this case we only ever modify the
  2973 		 * value once, so things work out well.
  2974 		 */
  2975 		ret = arenas[ind];
  2976 		if (ret == NULL) {
  2977 			/*
  2978 			 * Avoid races with another thread that may have already
  2979 			 * initialized arenas[ind].
  2980 			 */
  2981 			malloc_spin_lock(&arenas_lock);
  2982 			if (arenas[ind] == NULL)
  2983 				ret = arenas_extend((unsigned)ind);
  2984 			else
  2985 				ret = arenas[ind];
  2986 			malloc_spin_unlock(&arenas_lock);
  2988 	} else
  2989 		ret = arenas[0];
  2990 #endif
  2992 	RELEASE_ASSERT(ret != NULL);
  2993 	return (ret);
  2996 #ifndef NO_TLS
  2997 /*
  2998  * Choose an arena based on a per-thread value (slow-path code only, called
  2999  * only by choose_arena()).
  3000  */
  3001 static arena_t *
  3002 choose_arena_hard(void)
  3004 	arena_t *ret;
  3006 	assert(isthreaded);
  3008 #ifdef MALLOC_BALANCE
  3009 	/* Seed the PRNG used for arena load balancing. */
  3010 	SPRN(balance, (uint32_t)(uintptr_t)(_pthread_self()));
  3011 #endif
  3013 	if (narenas > 1) {
  3014 #ifdef MALLOC_BALANCE
  3015 		unsigned ind;
  3017 		ind = PRN(balance, narenas_2pow);
  3018 		if ((ret = arenas[ind]) == NULL) {
  3019 			malloc_spin_lock(&arenas_lock);
  3020 			if ((ret = arenas[ind]) == NULL)
  3021 				ret = arenas_extend(ind);
  3022 			malloc_spin_unlock(&arenas_lock);
  3024 #else
  3025 		malloc_spin_lock(&arenas_lock);
  3026 		if ((ret = arenas[next_arena]) == NULL)
  3027 			ret = arenas_extend(next_arena);
  3028 		next_arena = (next_arena + 1) % narenas;
  3029 		malloc_spin_unlock(&arenas_lock);
  3030 #endif
  3031 	} else
  3032 		ret = arenas[0];
  3034 #ifdef MOZ_MEMORY_WINDOWS
  3035 	TlsSetValue(tlsIndex, ret);
  3036 #else
  3037 	arenas_map = ret;
  3038 #endif
  3040 	return (ret);
  3042 #endif
  3044 static inline int
  3045 arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b)
  3047 	uintptr_t a_chunk = (uintptr_t)a;
  3048 	uintptr_t b_chunk = (uintptr_t)b;
  3050 	assert(a != NULL);
  3051 	assert(b != NULL);
  3053 	return ((a_chunk > b_chunk) - (a_chunk < b_chunk));
  3056 /* Wrap red-black tree macros in functions. */
  3057 rb_wrap(static, arena_chunk_tree_dirty_, arena_chunk_tree_t,
  3058     arena_chunk_t, link_dirty, arena_chunk_comp)
  3060 static inline int
  3061 arena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
  3063 	uintptr_t a_mapelm = (uintptr_t)a;
  3064 	uintptr_t b_mapelm = (uintptr_t)b;
  3066 	assert(a != NULL);
  3067 	assert(b != NULL);
  3069 	return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm));
  3072 /* Wrap red-black tree macros in functions. */
  3073 rb_wrap(static, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, link,
  3074     arena_run_comp)
  3076 static inline int
  3077 arena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b)
  3079 	int ret;
  3080 	size_t a_size = a->bits & ~pagesize_mask;
  3081 	size_t b_size = b->bits & ~pagesize_mask;
  3083 	ret = (a_size > b_size) - (a_size < b_size);
  3084 	if (ret == 0) {
  3085 		uintptr_t a_mapelm, b_mapelm;
  3087 		if ((a->bits & CHUNK_MAP_KEY) == 0)
  3088 			a_mapelm = (uintptr_t)a;
  3089 		else {
  3090 			/*
  3091 			 * Treat keys as though they are lower than anything
  3092 			 * else.
  3093 			 */
  3094 			a_mapelm = 0;
  3096 		b_mapelm = (uintptr_t)b;
  3098 		ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
  3101 	return (ret);
  3104 /* Wrap red-black tree macros in functions. */
  3105 rb_wrap(static, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, link,
  3106     arena_avail_comp)
  3108 static inline void *
  3109 arena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin)
  3111 	void *ret;
  3112 	unsigned i, mask, bit, regind;
  3114 	assert(run->magic == ARENA_RUN_MAGIC);
  3115 	assert(run->regs_minelm < bin->regs_mask_nelms);
  3117 	/*
  3118 	 * Move the first check outside the loop, so that run->regs_minelm can
  3119 	 * be updated unconditionally, without the possibility of updating it
  3120 	 * multiple times.
  3121 	 */
  3122 	i = run->regs_minelm;
  3123 	mask = run->regs_mask[i];
  3124 	if (mask != 0) {
  3125 		/* Usable allocation found. */
  3126 		bit = ffs((int)mask) - 1;
  3128 		regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
  3129 		assert(regind < bin->nregs);
  3130 		ret = (void *)(((uintptr_t)run) + bin->reg0_offset
  3131 		    + (bin->reg_size * regind));
  3133 		/* Clear bit. */
  3134 		mask ^= (1U << bit);
  3135 		run->regs_mask[i] = mask;
  3137 		return (ret);
  3140 	for (i++; i < bin->regs_mask_nelms; i++) {
  3141 		mask = run->regs_mask[i];
  3142 		if (mask != 0) {
  3143 			/* Usable allocation found. */
  3144 			bit = ffs((int)mask) - 1;
  3146 			regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
  3147 			assert(regind < bin->nregs);
  3148 			ret = (void *)(((uintptr_t)run) + bin->reg0_offset
  3149 			    + (bin->reg_size * regind));
  3151 			/* Clear bit. */
  3152 			mask ^= (1U << bit);
  3153 			run->regs_mask[i] = mask;
  3155 			/*
  3156 			 * Make a note that nothing before this element
  3157 			 * contains a free region.
  3158 			 */
  3159 			run->regs_minelm = i; /* Low payoff: + (mask == 0); */
  3161 			return (ret);
  3164 	/* Not reached. */
  3165 	RELEASE_ASSERT(0);
  3166 	return (NULL);
  3169 static inline void
  3170 arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size)
  3172 	/*
  3173 	 * To divide by a number D that is not a power of two we multiply
  3174 	 * by (2^21 / D) and then right shift by 21 positions.
  3176 	 *   X / D
  3178 	 * becomes
  3180 	 *   (X * size_invs[(D >> QUANTUM_2POW_MIN) - 3]) >> SIZE_INV_SHIFT
  3181 	 */
  3182 #define	SIZE_INV_SHIFT 21
  3183 #define	SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s << QUANTUM_2POW_MIN)) + 1)
  3184 	static const unsigned size_invs[] = {
  3185 	    SIZE_INV(3),
  3186 	    SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
  3187 	    SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
  3188 	    SIZE_INV(12),SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
  3189 	    SIZE_INV(16),SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
  3190 	    SIZE_INV(20),SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
  3191 	    SIZE_INV(24),SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
  3192 	    SIZE_INV(28),SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
  3193 #if (QUANTUM_2POW_MIN < 4)
  3195 	    SIZE_INV(32), SIZE_INV(33), SIZE_INV(34), SIZE_INV(35),
  3196 	    SIZE_INV(36), SIZE_INV(37), SIZE_INV(38), SIZE_INV(39),
  3197 	    SIZE_INV(40), SIZE_INV(41), SIZE_INV(42), SIZE_INV(43),
  3198 	    SIZE_INV(44), SIZE_INV(45), SIZE_INV(46), SIZE_INV(47),
  3199 	    SIZE_INV(48), SIZE_INV(49), SIZE_INV(50), SIZE_INV(51),
  3200 	    SIZE_INV(52), SIZE_INV(53), SIZE_INV(54), SIZE_INV(55),
  3201 	    SIZE_INV(56), SIZE_INV(57), SIZE_INV(58), SIZE_INV(59),
  3202 	    SIZE_INV(60), SIZE_INV(61), SIZE_INV(62), SIZE_INV(63)
  3203 #endif
  3204 	};
  3205 	unsigned diff, regind, elm, bit;
  3207 	assert(run->magic == ARENA_RUN_MAGIC);
  3208 	assert(((sizeof(size_invs)) / sizeof(unsigned)) + 3
  3209 	    >= (SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN));
  3211 	/*
  3212 	 * Avoid doing division with a variable divisor if possible.  Using
  3213 	 * actual division here can reduce allocator throughput by over 20%!
  3214 	 */
  3215 	diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset);
  3216 	if ((size & (size - 1)) == 0) {
  3217 		/*
  3218 		 * log2_table allows fast division of a power of two in the
  3219 		 * [1..128] range.
  3221 		 * (x / divisor) becomes (x >> log2_table[divisor - 1]).
  3222 		 */
  3223 		static const unsigned char log2_table[] = {
  3224 		    0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4,
  3225 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
  3226 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  3227 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6,
  3228 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  3229 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  3230 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  3231 		    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7
  3232 		};
  3234 		if (size <= 128)
  3235 			regind = (diff >> log2_table[size - 1]);
  3236 		else if (size <= 32768)
  3237 			regind = diff >> (8 + log2_table[(size >> 8) - 1]);
  3238 		else {
  3239 			/*
  3240 			 * The run size is too large for us to use the lookup
  3241 			 * table.  Use real division.
  3242 			 */
  3243 			regind = diff / size;
  3245 	} else if (size <= ((sizeof(size_invs) / sizeof(unsigned))
  3246 	    << QUANTUM_2POW_MIN) + 2) {
  3247 		regind = size_invs[(size >> QUANTUM_2POW_MIN) - 3] * diff;
  3248 		regind >>= SIZE_INV_SHIFT;
  3249 	} else {
  3250 		/*
  3251 		 * size_invs isn't large enough to handle this size class, so
  3252 		 * calculate regind using actual division.  This only happens
  3253 		 * if the user increases small_max via the 'S' runtime
  3254 		 * configuration option.
  3255 		 */
  3256 		regind = diff / size;
  3257 	};
  3258 	RELEASE_ASSERT(diff == regind * size);
  3259 	RELEASE_ASSERT(regind < bin->nregs);
  3261 	elm = regind >> (SIZEOF_INT_2POW + 3);
  3262 	if (elm < run->regs_minelm)
  3263 		run->regs_minelm = elm;
  3264 	bit = regind - (elm << (SIZEOF_INT_2POW + 3));
  3265 	RELEASE_ASSERT((run->regs_mask[elm] & (1U << bit)) == 0);
  3266 	run->regs_mask[elm] |= (1U << bit);
  3267 #undef SIZE_INV
  3268 #undef SIZE_INV_SHIFT
  3271 static void
  3272 arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
  3273     bool zero)
  3275 	arena_chunk_t *chunk;
  3276 	size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i;
  3278 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
  3279 	old_ndirty = chunk->ndirty;
  3280 	run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk)
  3281 	    >> pagesize_2pow);
  3282 	total_pages = (chunk->map[run_ind].bits & ~pagesize_mask) >>
  3283 	    pagesize_2pow;
  3284 	need_pages = (size >> pagesize_2pow);
  3285 	assert(need_pages > 0);
  3286 	assert(need_pages <= total_pages);
  3287 	rem_pages = total_pages - need_pages;
  3289 	arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]);
  3291 	/* Keep track of trailing unused pages for later use. */
  3292 	if (rem_pages > 0) {
  3293 		chunk->map[run_ind+need_pages].bits = (rem_pages <<
  3294 		    pagesize_2pow) | (chunk->map[run_ind+need_pages].bits &
  3295 		    pagesize_mask);
  3296 		chunk->map[run_ind+total_pages-1].bits = (rem_pages <<
  3297 		    pagesize_2pow) | (chunk->map[run_ind+total_pages-1].bits &
  3298 		    pagesize_mask);
  3299 		arena_avail_tree_insert(&arena->runs_avail,
  3300 		    &chunk->map[run_ind+need_pages]);
  3303 	for (i = 0; i < need_pages; i++) {
  3304 #if defined(MALLOC_DECOMMIT) || defined(MALLOC_STATS) || defined(MALLOC_DOUBLE_PURGE)
  3305 		/*
  3306 		 * Commit decommitted pages if necessary.  If a decommitted
  3307 		 * page is encountered, commit all needed adjacent decommitted
  3308 		 * pages in one operation, in order to reduce system call
  3309 		 * overhead.
  3310 		 */
  3311 		if (chunk->map[run_ind + i].bits & CHUNK_MAP_MADVISED_OR_DECOMMITTED) {
  3312 			size_t j;
  3314 			/*
  3315 			 * Advance i+j to just past the index of the last page
  3316 			 * to commit.  Clear CHUNK_MAP_DECOMMITTED and
  3317 			 * CHUNK_MAP_MADVISED along the way.
  3318 			 */
  3319 			for (j = 0; i + j < need_pages && (chunk->map[run_ind +
  3320 			    i + j].bits & CHUNK_MAP_MADVISED_OR_DECOMMITTED); j++) {
  3321 				/* DECOMMITTED and MADVISED are mutually exclusive. */
  3322 				assert(!(chunk->map[run_ind + i + j].bits & CHUNK_MAP_DECOMMITTED &&
  3323 					 chunk->map[run_ind + i + j].bits & CHUNK_MAP_MADVISED));
  3325 				chunk->map[run_ind + i + j].bits &=
  3326 				    ~CHUNK_MAP_MADVISED_OR_DECOMMITTED;
  3329 #  ifdef MALLOC_DECOMMIT
  3330 			pages_commit((void *)((uintptr_t)chunk + ((run_ind + i)
  3331 			    << pagesize_2pow)), (j << pagesize_2pow));
  3332 #    ifdef MALLOC_STATS
  3333 			arena->stats.ncommit++;
  3334 #    endif
  3335 #  endif
  3337 #  ifdef MALLOC_STATS
  3338 			arena->stats.committed += j;
  3339 #  endif
  3341 #  ifndef MALLOC_DECOMMIT
  3343 #  else
  3344 		} else /* No need to zero since commit zeros. */
  3345 #  endif
  3347 #endif
  3349 		/* Zero if necessary. */
  3350 		if (zero) {
  3351 			if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED)
  3352 			    == 0) {
  3353 				VALGRIND_MALLOCLIKE_BLOCK((void *)((uintptr_t)
  3354 				    chunk + ((run_ind + i) << pagesize_2pow)),
  3355 				    pagesize, 0, false);
  3356 				memset((void *)((uintptr_t)chunk + ((run_ind
  3357 				    + i) << pagesize_2pow)), 0, pagesize);
  3358 				VALGRIND_FREELIKE_BLOCK((void *)((uintptr_t)
  3359 				    chunk + ((run_ind + i) << pagesize_2pow)),
  3360 				    0);
  3361 				/* CHUNK_MAP_ZEROED is cleared below. */
  3365 		/* Update dirty page accounting. */
  3366 		if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) {
  3367 			chunk->ndirty--;
  3368 			arena->ndirty--;
  3369 			/* CHUNK_MAP_DIRTY is cleared below. */
  3372 		/* Initialize the chunk map. */
  3373 		if (large) {
  3374 			chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE
  3375 			    | CHUNK_MAP_ALLOCATED;
  3376 		} else {
  3377 			chunk->map[run_ind + i].bits = (size_t)run
  3378 			    | CHUNK_MAP_ALLOCATED;
  3382 	/*
  3383 	 * Set the run size only in the first element for large runs.  This is
  3384 	 * primarily a debugging aid, since the lack of size info for trailing
  3385 	 * pages only matters if the application tries to operate on an
  3386 	 * interior pointer.
  3387 	 */
  3388 	if (large)
  3389 		chunk->map[run_ind].bits |= size;
  3391 	if (chunk->ndirty == 0 && old_ndirty > 0)
  3392 		arena_chunk_tree_dirty_remove(&arena->chunks_dirty, chunk);
  3395 static void
  3396 arena_chunk_init(arena_t *arena, arena_chunk_t *chunk)
  3398 	arena_run_t *run;
  3399 	size_t i;
  3401 	VALGRIND_MALLOCLIKE_BLOCK(chunk, (arena_chunk_header_npages <<
  3402 	    pagesize_2pow), 0, false);
  3403 #ifdef MALLOC_STATS
  3404 	arena->stats.mapped += chunksize;
  3405 #endif
  3407 	chunk->arena = arena;
  3409 	/*
  3410 	 * Claim that no pages are in use, since the header is merely overhead.
  3411 	 */
  3412 	chunk->ndirty = 0;
  3414 	/* Initialize the map to contain one maximal free untouched run. */
  3415 	run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages <<
  3416 	    pagesize_2pow));
  3417 	for (i = 0; i < arena_chunk_header_npages; i++)
  3418 		chunk->map[i].bits = 0;
  3419 	chunk->map[i].bits = arena_maxclass | CHUNK_MAP_DECOMMITTED | CHUNK_MAP_ZEROED;
  3420 	for (i++; i < chunk_npages-1; i++) {
  3421 		chunk->map[i].bits = CHUNK_MAP_DECOMMITTED | CHUNK_MAP_ZEROED;
  3423 	chunk->map[chunk_npages-1].bits = arena_maxclass | CHUNK_MAP_DECOMMITTED | CHUNK_MAP_ZEROED;
  3425 #ifdef MALLOC_DECOMMIT
  3426 	/*
  3427 	 * Start out decommitted, in order to force a closer correspondence
  3428 	 * between dirty pages and committed untouched pages.
  3429 	 */
  3430 	pages_decommit(run, arena_maxclass);
  3431 #  ifdef MALLOC_STATS
  3432 	arena->stats.ndecommit++;
  3433 	arena->stats.decommitted += (chunk_npages - arena_chunk_header_npages);
  3434 #  endif
  3435 #endif
  3436 #ifdef MALLOC_STATS
  3437 	arena->stats.committed += arena_chunk_header_npages;
  3438 #endif
  3440 	/* Insert the run into the runs_avail tree. */
  3441 	arena_avail_tree_insert(&arena->runs_avail,
  3442 	    &chunk->map[arena_chunk_header_npages]);
  3444 #ifdef MALLOC_DOUBLE_PURGE
  3445 	LinkedList_Init(&chunk->chunks_madvised_elem);
  3446 #endif
  3449 static void
  3450 arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
  3453 	if (arena->spare != NULL) {
  3454 		if (arena->spare->ndirty > 0) {
  3455 			arena_chunk_tree_dirty_remove(
  3456 			    &chunk->arena->chunks_dirty, arena->spare);
  3457 			arena->ndirty -= arena->spare->ndirty;
  3458 #ifdef MALLOC_STATS
  3459 			arena->stats.committed -= arena->spare->ndirty;
  3460 #endif
  3463 #ifdef MALLOC_DOUBLE_PURGE
  3464 		/* This is safe to do even if arena->spare is not in the list. */
  3465 		LinkedList_Remove(&arena->spare->chunks_madvised_elem);
  3466 #endif
  3468 		VALGRIND_FREELIKE_BLOCK(arena->spare, 0);
  3469 		chunk_dealloc((void *)arena->spare, chunksize);
  3470 #ifdef MALLOC_STATS
  3471 		arena->stats.mapped -= chunksize;
  3472 		arena->stats.committed -= arena_chunk_header_npages;
  3473 #endif
  3476 	/*
  3477 	 * Remove run from runs_avail, so that the arena does not use it.
  3478 	 * Dirty page flushing only uses the chunks_dirty tree, so leaving this
  3479 	 * chunk in the chunks_* trees is sufficient for that purpose.
  3480 	 */
  3481 	arena_avail_tree_remove(&arena->runs_avail,
  3482 	    &chunk->map[arena_chunk_header_npages]);
  3484 	arena->spare = chunk;
  3487 static arena_run_t *
  3488 arena_run_alloc(arena_t *arena, arena_bin_t *bin, size_t size, bool large,
  3489     bool zero)
  3491 	arena_run_t *run;
  3492 	arena_chunk_map_t *mapelm, key;
  3494 	assert(size <= arena_maxclass);
  3495 	assert((size & pagesize_mask) == 0);
  3497 	/* Search the arena's chunks for the lowest best fit. */
  3498 	key.bits = size | CHUNK_MAP_KEY;
  3499 	mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key);
  3500 	if (mapelm != NULL) {
  3501 		arena_chunk_t *chunk =
  3502 		    (arena_chunk_t*)CHUNK_ADDR2BASE(mapelm);
  3503 		size_t pageind = ((uintptr_t)mapelm -
  3504 		    (uintptr_t)chunk->map) /
  3505 		    sizeof(arena_chunk_map_t);
  3507 		run = (arena_run_t *)((uintptr_t)chunk + (pageind
  3508 		    << pagesize_2pow));
  3509 		arena_run_split(arena, run, size, large, zero);
  3510 		return (run);
  3513 	if (arena->spare != NULL) {
  3514 		/* Use the spare. */
  3515 		arena_chunk_t *chunk = arena->spare;
  3516 		arena->spare = NULL;
  3517 		run = (arena_run_t *)((uintptr_t)chunk +
  3518 		    (arena_chunk_header_npages << pagesize_2pow));
  3519 		/* Insert the run into the runs_avail tree. */
  3520 		arena_avail_tree_insert(&arena->runs_avail,
  3521 		    &chunk->map[arena_chunk_header_npages]);
  3522 		arena_run_split(arena, run, size, large, zero);
  3523 		return (run);
  3526 	/*
  3527 	 * No usable runs.  Create a new chunk from which to allocate
  3528 	 * the run.
  3529 	 */
  3531 		arena_chunk_t *chunk = (arena_chunk_t *)
  3532 		    chunk_alloc(chunksize, true, true);
  3533 		if (chunk == NULL)
  3534 			return (NULL);
  3536 		arena_chunk_init(arena, chunk);
  3537 		run = (arena_run_t *)((uintptr_t)chunk +
  3538 		    (arena_chunk_header_npages << pagesize_2pow));
  3540 	/* Update page map. */
  3541 	arena_run_split(arena, run, size, large, zero);
  3542 	return (run);
  3545 static void
  3546 arena_purge(arena_t *arena, bool all)
  3548 	arena_chunk_t *chunk;
  3549 	size_t i, npages;
  3550 	/* If all is set purge all dirty pages. */
  3551 	size_t dirty_max = all ? 1 : opt_dirty_max;
  3552 #ifdef MALLOC_DEBUG
  3553 	size_t ndirty = 0;
  3554 	rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty,
  3555 	    chunk) {
  3556 		ndirty += chunk->ndirty;
  3557 	} rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk)
  3558 	assert(ndirty == arena->ndirty);
  3559 #endif
  3560 	RELEASE_ASSERT(all || (arena->ndirty > opt_dirty_max));
  3562 #ifdef MALLOC_STATS
  3563 	arena->stats.npurge++;
  3564 #endif
  3566 	/*
  3567 	 * Iterate downward through chunks until enough dirty memory has been
  3568 	 * purged.  Terminate as soon as possible in order to minimize the
  3569 	 * number of system calls, even if a chunk has only been partially
  3570 	 * purged.
  3571 	 */
  3572 	while (arena->ndirty > (dirty_max >> 1)) {
  3573 #ifdef MALLOC_DOUBLE_PURGE
  3574 		bool madvised = false;
  3575 #endif
  3576 		chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty);
  3577 		RELEASE_ASSERT(chunk != NULL);
  3579 		for (i = chunk_npages - 1; chunk->ndirty > 0; i--) {
  3580 			RELEASE_ASSERT(i >= arena_chunk_header_npages);
  3582 			if (chunk->map[i].bits & CHUNK_MAP_DIRTY) {
  3583 #ifdef MALLOC_DECOMMIT
  3584 				const size_t free_operation = CHUNK_MAP_DECOMMITTED;
  3585 #else
  3586 				const size_t free_operation = CHUNK_MAP_MADVISED;
  3587 #endif
  3588 				assert((chunk->map[i].bits &
  3589 				        CHUNK_MAP_MADVISED_OR_DECOMMITTED) == 0);
  3590 				chunk->map[i].bits ^= free_operation | CHUNK_MAP_DIRTY;
  3591 				/* Find adjacent dirty run(s). */
  3592 				for (npages = 1;
  3593 				     i > arena_chunk_header_npages &&
  3594 				       (chunk->map[i - 1].bits & CHUNK_MAP_DIRTY);
  3595 				     npages++) {
  3596 					i--;
  3597 					assert((chunk->map[i].bits &
  3598 					        CHUNK_MAP_MADVISED_OR_DECOMMITTED) == 0);
  3599 					chunk->map[i].bits ^= free_operation | CHUNK_MAP_DIRTY;
  3601 				chunk->ndirty -= npages;
  3602 				arena->ndirty -= npages;
  3604 #ifdef MALLOC_DECOMMIT
  3605 				pages_decommit((void *)((uintptr_t)
  3606 				    chunk + (i << pagesize_2pow)),
  3607 				    (npages << pagesize_2pow));
  3608 #  ifdef MALLOC_STATS
  3609 				arena->stats.ndecommit++;
  3610 				arena->stats.decommitted += npages;
  3611 #  endif
  3612 #endif
  3613 #ifdef MALLOC_STATS
  3614 				arena->stats.committed -= npages;
  3615 #endif
  3617 #ifndef MALLOC_DECOMMIT
  3618 				madvise((void *)((uintptr_t)chunk + (i <<
  3619 				    pagesize_2pow)), (npages << pagesize_2pow),
  3620 				    MADV_FREE);
  3621 #  ifdef MALLOC_DOUBLE_PURGE
  3622 				madvised = true;
  3623 #  endif
  3624 #endif
  3625 #ifdef MALLOC_STATS
  3626 				arena->stats.nmadvise++;
  3627 				arena->stats.purged += npages;
  3628 #endif
  3629 				if (arena->ndirty <= (dirty_max >> 1))
  3630 					break;
  3634 		if (chunk->ndirty == 0) {
  3635 			arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
  3636 			    chunk);
  3638 #ifdef MALLOC_DOUBLE_PURGE
  3639 		if (madvised) {
  3640 			/* The chunk might already be in the list, but this
  3641 			 * makes sure it's at the front. */
  3642 			LinkedList_Remove(&chunk->chunks_madvised_elem);
  3643 			LinkedList_InsertHead(&arena->chunks_madvised, &chunk->chunks_madvised_elem);
  3645 #endif
  3649 static void
  3650 arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
  3652 	arena_chunk_t *chunk;
  3653 	size_t size, run_ind, run_pages;
  3655 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run);
  3656 	run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk)
  3657 	    >> pagesize_2pow);
  3658 	RELEASE_ASSERT(run_ind >= arena_chunk_header_npages);
  3659 	RELEASE_ASSERT(run_ind < chunk_npages);
  3660 	if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0)
  3661 		size = chunk->map[run_ind].bits & ~pagesize_mask;
  3662 	else
  3663 		size = run->bin->run_size;
  3664 	run_pages = (size >> pagesize_2pow);
  3666 	/* Mark pages as unallocated in the chunk map. */
  3667 	if (dirty) {
  3668 		size_t i;
  3670 		for (i = 0; i < run_pages; i++) {
  3671 			RELEASE_ASSERT((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY)
  3672 			    == 0);
  3673 			chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY;
  3676 		if (chunk->ndirty == 0) {
  3677 			arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
  3678 			    chunk);
  3680 		chunk->ndirty += run_pages;
  3681 		arena->ndirty += run_pages;
  3682 	} else {
  3683 		size_t i;
  3685 		for (i = 0; i < run_pages; i++) {
  3686 			chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE |
  3687 			    CHUNK_MAP_ALLOCATED);
  3690 	chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
  3691 	    pagesize_mask);
  3692 	chunk->map[run_ind+run_pages-1].bits = size |
  3693 	    (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
  3695 	/* Try to coalesce forward. */
  3696 	if (run_ind + run_pages < chunk_npages &&
  3697 	    (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) {
  3698 		size_t nrun_size = chunk->map[run_ind+run_pages].bits &
  3699 		    ~pagesize_mask;
  3701 		/*
  3702 		 * Remove successor from runs_avail; the coalesced run is
  3703 		 * inserted later.
  3704 		 */
  3705 		arena_avail_tree_remove(&arena->runs_avail,
  3706 		    &chunk->map[run_ind+run_pages]);
  3708 		size += nrun_size;
  3709 		run_pages = size >> pagesize_2pow;
  3711 		RELEASE_ASSERT((chunk->map[run_ind+run_pages-1].bits & ~pagesize_mask)
  3712 		    == nrun_size);
  3713 		chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
  3714 		    pagesize_mask);
  3715 		chunk->map[run_ind+run_pages-1].bits = size |
  3716 		    (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
  3719 	/* Try to coalesce backward. */
  3720 	if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits &
  3721 	    CHUNK_MAP_ALLOCATED) == 0) {
  3722 		size_t prun_size = chunk->map[run_ind-1].bits & ~pagesize_mask;
  3724 		run_ind -= prun_size >> pagesize_2pow;
  3726 		/*
  3727 		 * Remove predecessor from runs_avail; the coalesced run is
  3728 		 * inserted later.
  3729 		 */
  3730 		arena_avail_tree_remove(&arena->runs_avail,
  3731 		    &chunk->map[run_ind]);
  3733 		size += prun_size;
  3734 		run_pages = size >> pagesize_2pow;
  3736 		RELEASE_ASSERT((chunk->map[run_ind].bits & ~pagesize_mask) ==
  3737 		    prun_size);
  3738 		chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits &
  3739 		    pagesize_mask);
  3740 		chunk->map[run_ind+run_pages-1].bits = size |
  3741 		    (chunk->map[run_ind+run_pages-1].bits & pagesize_mask);
  3744 	/* Insert into runs_avail, now that coalescing is complete. */
  3745 	arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]);
  3747 	/* Deallocate chunk if it is now completely unused. */
  3748 	if ((chunk->map[arena_chunk_header_npages].bits & (~pagesize_mask |
  3749 	    CHUNK_MAP_ALLOCATED)) == arena_maxclass)
  3750 		arena_chunk_dealloc(arena, chunk);
  3752 	/* Enforce opt_dirty_max. */
  3753 	if (arena->ndirty > opt_dirty_max)
  3754 		arena_purge(arena, false);
  3757 static void
  3758 arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
  3759     size_t oldsize, size_t newsize)
  3761 	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
  3762 	size_t head_npages = (oldsize - newsize) >> pagesize_2pow;
  3764 	assert(oldsize > newsize);
  3766 	/*
  3767 	 * Update the chunk map so that arena_run_dalloc() can treat the
  3768 	 * leading run as separately allocated.
  3769 	 */
  3770 	chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE |
  3771 	    CHUNK_MAP_ALLOCATED;
  3772 	chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE |
  3773 	    CHUNK_MAP_ALLOCATED;
  3775 	arena_run_dalloc(arena, run, false);
  3778 static void
  3779 arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run,
  3780     size_t oldsize, size_t newsize, bool dirty)
  3782 	size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> pagesize_2pow;
  3783 	size_t npages = newsize >> pagesize_2pow;
  3785 	assert(oldsize > newsize);
  3787 	/*
  3788 	 * Update the chunk map so that arena_run_dalloc() can treat the
  3789 	 * trailing run as separately allocated.
  3790 	 */
  3791 	chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE |
  3792 	    CHUNK_MAP_ALLOCATED;
  3793 	chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE
  3794 	    | CHUNK_MAP_ALLOCATED;
  3796 	arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize),
  3797 	    dirty);
  3800 static arena_run_t *
  3801 arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
  3803 	arena_chunk_map_t *mapelm;
  3804 	arena_run_t *run;
  3805 	unsigned i, remainder;
  3807 	/* Look for a usable run. */
  3808 	mapelm = arena_run_tree_first(&bin->runs);
  3809 	if (mapelm != NULL) {
  3810 		/* run is guaranteed to have available space. */
  3811 		arena_run_tree_remove(&bin->runs, mapelm);
  3812 		run = (arena_run_t *)(mapelm->bits & ~pagesize_mask);
  3813 #ifdef MALLOC_STATS
  3814 		bin->stats.reruns++;
  3815 #endif
  3816 		return (run);
  3818 	/* No existing runs have any space available. */
  3820 	/* Allocate a new run. */
  3821 	run = arena_run_alloc(arena, bin, bin->run_size, false, false);
  3822 	if (run == NULL)
  3823 		return (NULL);
  3824 	/*
  3825 	 * Don't initialize if a race in arena_run_alloc() allowed an existing
  3826 	 * run to become usable.
  3827 	 */
  3828 	if (run == bin->runcur)
  3829 		return (run);
  3831 	VALGRIND_MALLOCLIKE_BLOCK(run, sizeof(arena_run_t) + (sizeof(unsigned) *
  3832 	    (bin->regs_mask_nelms - 1)), 0, false);
  3834 	/* Initialize run internals. */
  3835 	run->bin = bin;
  3837 	for (i = 0; i < bin->regs_mask_nelms - 1; i++)
  3838 		run->regs_mask[i] = UINT_MAX;
  3839 	remainder = bin->nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1);
  3840 	if (remainder == 0)
  3841 		run->regs_mask[i] = UINT_MAX;
  3842 	else {
  3843 		/* The last element has spare bits that need to be unset. */
  3844 		run->regs_mask[i] = (UINT_MAX >> ((1U << (SIZEOF_INT_2POW + 3))
  3845 		    - remainder));
  3848 	run->regs_minelm = 0;
  3850 	run->nfree = bin->nregs;
  3851 #if defined(MALLOC_DEBUG) || defined(MOZ_JEMALLOC_HARD_ASSERTS)
  3852 	run->magic = ARENA_RUN_MAGIC;
  3853 #endif
  3855 #ifdef MALLOC_STATS
  3856 	bin->stats.nruns++;
  3857 	bin->stats.curruns++;
  3858 	if (bin->stats.curruns > bin->stats.highruns)
  3859 		bin->stats.highruns = bin->stats.curruns;
  3860 #endif
  3861 	return (run);
  3864 /* bin->runcur must have space available before this function is called. */
  3865 static inline void *
  3866 arena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run)
  3868 	void *ret;
  3870 	RELEASE_ASSERT(run->magic == ARENA_RUN_MAGIC);
  3871 	RELEASE_ASSERT(run->nfree > 0);
  3873 	ret = arena_run_reg_alloc(run, bin);
  3874 	RELEASE_ASSERT(ret != NULL);
  3875 	run->nfree--;
  3877 	return (ret);
  3880 /* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */
  3881 static void *
  3882 arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin)
  3885 	bin->runcur = arena_bin_nonfull_run_get(arena, bin);
  3886 	if (bin->runcur == NULL)
  3887 		return (NULL);
  3888 	RELEASE_ASSERT(bin->runcur->magic == ARENA_RUN_MAGIC);
  3889 	RELEASE_ASSERT(bin->runcur->nfree > 0);
  3891 	return (arena_bin_malloc_easy(arena, bin, bin->runcur));
  3894 /*
  3895  * Calculate bin->run_size such that it meets the following constraints:
  3897  *   *) bin->run_size >= min_run_size
  3898  *   *) bin->run_size <= arena_maxclass
  3899  *   *) bin->run_size <= RUN_MAX_SMALL
  3900  *   *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed).
  3902  * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are
  3903  * also calculated here, since these settings are all interdependent.
  3904  */
  3905 static size_t
  3906 arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size)
  3908 	size_t try_run_size, good_run_size;
  3909 	unsigned good_nregs, good_mask_nelms, good_reg0_offset;
  3910 	unsigned try_nregs, try_mask_nelms, try_reg0_offset;
  3912 	assert(min_run_size >= pagesize);
  3913 	assert(min_run_size <= arena_maxclass);
  3914 	assert(min_run_size <= RUN_MAX_SMALL);
  3916 	/*
  3917 	 * Calculate known-valid settings before entering the run_size
  3918 	 * expansion loop, so that the first part of the loop always copies
  3919 	 * valid settings.
  3921 	 * The do..while loop iteratively reduces the number of regions until
  3922 	 * the run header and the regions no longer overlap.  A closed formula
  3923 	 * would be quite messy, since there is an interdependency between the
  3924 	 * header's mask length and the number of regions.
  3925 	 */
  3926 	try_run_size = min_run_size;
  3927 	try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size)
  3928 	    + 1; /* Counter-act try_nregs-- in loop. */
  3929 	do {
  3930 		try_nregs--;
  3931 		try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
  3932 		    ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ? 1 : 0);
  3933 		try_reg0_offset = try_run_size - (try_nregs * bin->reg_size);
  3934 	} while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1))
  3935 	    > try_reg0_offset);
  3937 	/* run_size expansion loop. */
  3938 	do {
  3939 		/*
  3940 		 * Copy valid settings before trying more aggressive settings.
  3941 		 */
  3942 		good_run_size = try_run_size;
  3943 		good_nregs = try_nregs;
  3944 		good_mask_nelms = try_mask_nelms;
  3945 		good_reg0_offset = try_reg0_offset;
  3947 		/* Try more aggressive settings. */
  3948 		try_run_size += pagesize;
  3949 		try_nregs = ((try_run_size - sizeof(arena_run_t)) /
  3950 		    bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */
  3951 		do {
  3952 			try_nregs--;
  3953 			try_mask_nelms = (try_nregs >> (SIZEOF_INT_2POW + 3)) +
  3954 			    ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ?
  3955 			    1 : 0);
  3956 			try_reg0_offset = try_run_size - (try_nregs *
  3957 			    bin->reg_size);
  3958 		} while (sizeof(arena_run_t) + (sizeof(unsigned) *
  3959 		    (try_mask_nelms - 1)) > try_reg0_offset);
  3960 	} while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL
  3961 	    && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX
  3962 	    && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
  3964 	assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1))
  3965 	    <= good_reg0_offset);
  3966 	assert((good_mask_nelms << (SIZEOF_INT_2POW + 3)) >= good_nregs);
  3968 	/* Copy final settings. */
  3969 	bin->run_size = good_run_size;
  3970 	bin->nregs = good_nregs;
  3971 	bin->regs_mask_nelms = good_mask_nelms;
  3972 	bin->reg0_offset = good_reg0_offset;
  3974 	return (good_run_size);
  3977 #ifdef MALLOC_BALANCE
  3978 static inline void
  3979 arena_lock_balance(arena_t *arena)
  3981 	unsigned contention;
  3983 	contention = malloc_spin_lock(&arena->lock);
  3984 	if (narenas > 1) {
  3985 		/*
  3986 		 * Calculate the exponentially averaged contention for this
  3987 		 * arena.  Due to integer math always rounding down, this value
  3988 		 * decays somewhat faster then normal.
  3989 		 */
  3990 		arena->contention = (((uint64_t)arena->contention
  3991 		    * (uint64_t)((1U << BALANCE_ALPHA_INV_2POW)-1))
  3992 		    + (uint64_t)contention) >> BALANCE_ALPHA_INV_2POW;
  3993 		if (arena->contention >= opt_balance_threshold)
  3994 			arena_lock_balance_hard(arena);
  3998 static void
  3999 arena_lock_balance_hard(arena_t *arena)
  4001 	uint32_t ind;
  4003 	arena->contention = 0;
  4004 #ifdef MALLOC_STATS
  4005 	arena->stats.nbalance++;
  4006 #endif
  4007 	ind = PRN(balance, narenas_2pow);
  4008 	if (arenas[ind] != NULL) {
  4009 #ifdef MOZ_MEMORY_WINDOWS
  4010 		TlsSetValue(tlsIndex, arenas[ind]);
  4011 #else
  4012 		arenas_map = arenas[ind];
  4013 #endif
  4014 	} else {
  4015 		malloc_spin_lock(&arenas_lock);
  4016 		if (arenas[ind] != NULL) {
  4017 #ifdef MOZ_MEMORY_WINDOWS
  4018 			TlsSetValue(tlsIndex, arenas[ind]);
  4019 #else
  4020 			arenas_map = arenas[ind];
  4021 #endif
  4022 		} else {
  4023 #ifdef MOZ_MEMORY_WINDOWS
  4024 			TlsSetValue(tlsIndex, arenas_extend(ind));
  4025 #else
  4026 			arenas_map = arenas_extend(ind);
  4027 #endif
  4029 		malloc_spin_unlock(&arenas_lock);
  4032 #endif
  4034 static inline void *
  4035 arena_malloc_small(arena_t *arena, size_t size, bool zero)
  4037 	void *ret;
  4038 	arena_bin_t *bin;
  4039 	arena_run_t *run;
  4041 	if (size < small_min) {
  4042 		/* Tiny. */
  4043 		size = pow2_ceil(size);
  4044 		bin = &arena->bins[ffs((int)(size >> (TINY_MIN_2POW +
  4045 		    1)))];
  4046 #if (!defined(NDEBUG) || defined(MALLOC_STATS))
  4047 		/*
  4048 		 * Bin calculation is always correct, but we may need
  4049 		 * to fix size for the purposes of assertions and/or
  4050 		 * stats accuracy.
  4051 		 */
  4052 		if (size < (1U << TINY_MIN_2POW))
  4053 			size = (1U << TINY_MIN_2POW);
  4054 #endif
  4055 	} else if (size <= small_max) {
  4056 		/* Quantum-spaced. */
  4057 		size = QUANTUM_CEILING(size);
  4058 		bin = &arena->bins[ntbins + (size >> opt_quantum_2pow)
  4059 		    - 1];
  4060 	} else {
  4061 		/* Sub-page. */
  4062 		size = pow2_ceil(size);
  4063 		bin = &arena->bins[ntbins + nqbins
  4064 		    + (ffs((int)(size >> opt_small_max_2pow)) - 2)];
  4066 	RELEASE_ASSERT(size == bin->reg_size);
  4068 #ifdef MALLOC_BALANCE
  4069 	arena_lock_balance(arena);
  4070 #else
  4071 	malloc_spin_lock(&arena->lock);
  4072 #endif
  4073 	if ((run = bin->runcur) != NULL && run->nfree > 0)
  4074 		ret = arena_bin_malloc_easy(arena, bin, run);
  4075 	else
  4076 		ret = arena_bin_malloc_hard(arena, bin);
  4078 	if (ret == NULL) {
  4079 		malloc_spin_unlock(&arena->lock);
  4080 		return (NULL);
  4083 #ifdef MALLOC_STATS
  4084 	bin->stats.nrequests++;
  4085 	arena->stats.nmalloc_small++;
  4086 	arena->stats.allocated_small += size;
  4087 #endif
  4088 	malloc_spin_unlock(&arena->lock);
  4090 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
  4091 	if (zero == false) {
  4092 #ifdef MALLOC_FILL
  4093 		if (opt_junk)
  4094 			memset(ret, 0xa5, size);
  4095 		else if (opt_zero)
  4096 			memset(ret, 0, size);
  4097 #endif
  4098 	} else
  4099 		memset(ret, 0, size);
  4101 	return (ret);
  4104 static void *
  4105 arena_malloc_large(arena_t *arena, size_t size, bool zero)
  4107 	void *ret;
  4109 	/* Large allocation. */
  4110 	size = PAGE_CEILING(size);
  4111 #ifdef MALLOC_BALANCE
  4112 	arena_lock_balance(arena);
  4113 #else
  4114 	malloc_spin_lock(&arena->lock);
  4115 #endif
  4116 	ret = (void *)arena_run_alloc(arena, NULL, size, true, zero);
  4117 	if (ret == NULL) {
  4118 		malloc_spin_unlock(&arena->lock);
  4119 		return (NULL);
  4121 #ifdef MALLOC_STATS
  4122 	arena->stats.nmalloc_large++;
  4123 	arena->stats.allocated_large += size;
  4124 #endif
  4125 	malloc_spin_unlock(&arena->lock);
  4127 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, zero);
  4128 	if (zero == false) {
  4129 #ifdef MALLOC_FILL
  4130 		if (opt_junk)
  4131 			memset(ret, 0xa5, size);
  4132 		else if (opt_zero)
  4133 			memset(ret, 0, size);
  4134 #endif
  4137 	return (ret);
  4140 static inline void *
  4141 arena_malloc(arena_t *arena, size_t size, bool zero)
  4144 	assert(arena != NULL);
  4145 	RELEASE_ASSERT(arena->magic == ARENA_MAGIC);
  4146 	assert(size != 0);
  4147 	assert(QUANTUM_CEILING(size) <= arena_maxclass);
  4149 	if (size <= bin_maxclass) {
  4150 		return (arena_malloc_small(arena, size, zero));
  4151 	} else
  4152 		return (arena_malloc_large(arena, size, zero));
  4155 static inline void *
  4156 imalloc(size_t size)
  4159 	assert(size != 0);
  4161 	if (size <= arena_maxclass)
  4162 		return (arena_malloc(choose_arena(), size, false));
  4163 	else
  4164 		return (huge_malloc(size, false));
  4167 static inline void *
  4168 icalloc(size_t size)
  4171 	if (size <= arena_maxclass)
  4172 		return (arena_malloc(choose_arena(), size, true));
  4173 	else
  4174 		return (huge_malloc(size, true));
  4177 /* Only handles large allocations that require more than page alignment. */
  4178 static void *
  4179 arena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size)
  4181 	void *ret;
  4182 	size_t offset;
  4183 	arena_chunk_t *chunk;
  4185 	assert((size & pagesize_mask) == 0);
  4186 	assert((alignment & pagesize_mask) == 0);
  4188 #ifdef MALLOC_BALANCE
  4189 	arena_lock_balance(arena);
  4190 #else
  4191 	malloc_spin_lock(&arena->lock);
  4192 #endif
  4193 	ret = (void *)arena_run_alloc(arena, NULL, alloc_size, true, false);
  4194 	if (ret == NULL) {
  4195 		malloc_spin_unlock(&arena->lock);
  4196 		return (NULL);
  4199 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret);
  4201 	offset = (uintptr_t)ret & (alignment - 1);
  4202 	assert((offset & pagesize_mask) == 0);
  4203 	assert(offset < alloc_size);
  4204 	if (offset == 0)
  4205 		arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, alloc_size, size, false);
  4206 	else {
  4207 		size_t leadsize, trailsize;
  4209 		leadsize = alignment - offset;
  4210 		if (leadsize > 0) {
  4211 			arena_run_trim_head(arena, chunk, (arena_run_t*)ret, alloc_size,
  4212 			    alloc_size - leadsize);
  4213 			ret = (void *)((uintptr_t)ret + leadsize);
  4216 		trailsize = alloc_size - leadsize - size;
  4217 		if (trailsize != 0) {
  4218 			/* Trim trailing space. */
  4219 			assert(trailsize < alloc_size);
  4220 			arena_run_trim_tail(arena, chunk, (arena_run_t*)ret, size + trailsize,
  4221 			    size, false);
  4225 #ifdef MALLOC_STATS
  4226 	arena->stats.nmalloc_large++;
  4227 	arena->stats.allocated_large += size;
  4228 #endif
  4229 	malloc_spin_unlock(&arena->lock);
  4231 	VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
  4232 #ifdef MALLOC_FILL
  4233 	if (opt_junk)
  4234 		memset(ret, 0xa5, size);
  4235 	else if (opt_zero)
  4236 		memset(ret, 0, size);
  4237 #endif
  4238 	return (ret);
  4241 static inline void *
  4242 ipalloc(size_t alignment, size_t size)
  4244 	void *ret;
  4245 	size_t ceil_size;
  4247 	/*
  4248 	 * Round size up to the nearest multiple of alignment.
  4250 	 * This done, we can take advantage of the fact that for each small
  4251 	 * size class, every object is aligned at the smallest power of two
  4252 	 * that is non-zero in the base two representation of the size.  For
  4253 	 * example:
  4255 	 *   Size |   Base 2 | Minimum alignment
  4256 	 *   -----+----------+------------------
  4257 	 *     96 |  1100000 |  32
  4258 	 *    144 | 10100000 |  32
  4259 	 *    192 | 11000000 |  64
  4261 	 * Depending on runtime settings, it is possible that arena_malloc()
  4262 	 * will further round up to a power of two, but that never causes
  4263 	 * correctness issues.
  4264 	 */
  4265 	ceil_size = (size + (alignment - 1)) & (-alignment);
  4266 	/*
  4267 	 * (ceil_size < size) protects against the combination of maximal
  4268 	 * alignment and size greater than maximal alignment.
  4269 	 */
  4270 	if (ceil_size < size) {
  4271 		/* size_t overflow. */
  4272 		return (NULL);
  4275 	if (ceil_size <= pagesize || (alignment <= pagesize
  4276 	    && ceil_size <= arena_maxclass))
  4277 		ret = arena_malloc(choose_arena(), ceil_size, false);
  4278 	else {
  4279 		size_t run_size;
  4281 		/*
  4282 		 * We can't achieve sub-page alignment, so round up alignment
  4283 		 * permanently; it makes later calculations simpler.
  4284 		 */
  4285 		alignment = PAGE_CEILING(alignment);
  4286 		ceil_size = PAGE_CEILING(size);
  4287 		/*
  4288 		 * (ceil_size < size) protects against very large sizes within
  4289 		 * pagesize of SIZE_T_MAX.
  4291 		 * (ceil_size + alignment < ceil_size) protects against the
  4292 		 * combination of maximal alignment and ceil_size large enough
  4293 		 * to cause overflow.  This is similar to the first overflow
  4294 		 * check above, but it needs to be repeated due to the new
  4295 		 * ceil_size value, which may now be *equal* to maximal
  4296 		 * alignment, whereas before we only detected overflow if the
  4297 		 * original size was *greater* than maximal alignment.
  4298 		 */
  4299 		if (ceil_size < size || ceil_size + alignment < ceil_size) {
  4300 			/* size_t overflow. */
  4301 			return (NULL);
  4304 		/*
  4305 		 * Calculate the size of the over-size run that arena_palloc()
  4306 		 * would need to allocate in order to guarantee the alignment.
  4307 		 */
  4308 		if (ceil_size >= alignment)
  4309 			run_size = ceil_size + alignment - pagesize;
  4310 		else {
  4311 			/*
  4312 			 * It is possible that (alignment << 1) will cause
  4313 			 * overflow, but it doesn't matter because we also
  4314 			 * subtract pagesize, which in the case of overflow
  4315 			 * leaves us with a very large run_size.  That causes
  4316 			 * the first conditional below to fail, which means
  4317 			 * that the bogus run_size value never gets used for
  4318 			 * anything important.
  4319 			 */
  4320 			run_size = (alignment << 1) - pagesize;
  4323 		if (run_size <= arena_maxclass) {
  4324 			ret = arena_palloc(choose_arena(), alignment, ceil_size,
  4325 			    run_size);
  4326 		} else if (alignment <= chunksize)
  4327 			ret = huge_malloc(ceil_size, false);
  4328 		else
  4329 			ret = huge_palloc(alignment, ceil_size);
  4332 	assert(((uintptr_t)ret & (alignment - 1)) == 0);
  4333 	return (ret);
  4336 /* Return the size of the allocation pointed to by ptr. */
  4337 static size_t
  4338 arena_salloc(const void *ptr)
  4340 	size_t ret;
  4341 	arena_chunk_t *chunk;
  4342 	size_t pageind, mapbits;
  4344 	assert(ptr != NULL);
  4345 	assert(CHUNK_ADDR2BASE(ptr) != ptr);
  4347 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
  4348 	pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow);
  4349 	mapbits = chunk->map[pageind].bits;
  4350 	RELEASE_ASSERT((mapbits & CHUNK_MAP_ALLOCATED) != 0);
  4351 	if ((mapbits & CHUNK_MAP_LARGE) == 0) {
  4352 		arena_run_t *run = (arena_run_t *)(mapbits & ~pagesize_mask);
  4353 		RELEASE_ASSERT(run->magic == ARENA_RUN_MAGIC);
  4354 		ret = run->bin->reg_size;
  4355 	} else {
  4356 		ret = mapbits & ~pagesize_mask;
  4357 		RELEASE_ASSERT(ret != 0);
  4360 	return (ret);
  4363 #if (defined(MALLOC_VALIDATE) || defined(MOZ_MEMORY_DARWIN))
  4364 /*
  4365  * Validate ptr before assuming that it points to an allocation.  Currently,
  4366  * the following validation is performed:
  4368  * + Check that ptr is not NULL.
  4370  * + Check that ptr lies within a mapped chunk.
  4371  */
  4372 static inline size_t
  4373 isalloc_validate(const void *ptr)
  4375 	arena_chunk_t *chunk;
  4377 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
  4378 	if (chunk == NULL)
  4379 		return (0);
  4381 	if (malloc_rtree_get(chunk_rtree, (uintptr_t)chunk) == NULL)
  4382 		return (0);
  4384 	if (chunk != ptr) {
  4385 		RELEASE_ASSERT(chunk->arena->magic == ARENA_MAGIC);
  4386 		return (arena_salloc(ptr));
  4387 	} else {
  4388 		size_t ret;
  4389 		extent_node_t *node;
  4390 		extent_node_t key;
  4392 		/* Chunk. */
  4393 		key.addr = (void *)chunk;
  4394 		malloc_mutex_lock(&huge_mtx);
  4395 		node = extent_tree_ad_search(&huge, &key);
  4396 		if (node != NULL)
  4397 			ret = node->size;
  4398 		else
  4399 			ret = 0;
  4400 		malloc_mutex_unlock(&huge_mtx);
  4401 		return (ret);
  4404 #endif
  4406 static inline size_t
  4407 isalloc(const void *ptr)
  4409 	size_t ret;
  4410 	arena_chunk_t *chunk;
  4412 	assert(ptr != NULL);
  4414 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
  4415 	if (chunk != ptr) {
  4416 		/* Region. */
  4417 		assert(chunk->arena->magic == ARENA_MAGIC);
  4419 		ret = arena_salloc(ptr);
  4420 	} else {
  4421 		extent_node_t *node, key;
  4423 		/* Chunk (huge allocation). */
  4425 		malloc_mutex_lock(&huge_mtx);
  4427 		/* Extract from tree of huge allocations. */
  4428 		key.addr = __DECONST(void *, ptr);
  4429 		node = extent_tree_ad_search(&huge, &key);
  4430 		RELEASE_ASSERT(node != NULL);
  4432 		ret = node->size;
  4434 		malloc_mutex_unlock(&huge_mtx);
  4437 	return (ret);
  4440 static inline void
  4441 arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
  4442     arena_chunk_map_t *mapelm)
  4444 	arena_run_t *run;
  4445 	arena_bin_t *bin;
  4446 	size_t size;
  4448 	run = (arena_run_t *)(mapelm->bits & ~pagesize_mask);
  4449 	RELEASE_ASSERT(run->magic == ARENA_RUN_MAGIC);
  4450 	bin = run->bin;
  4451 	size = bin->reg_size;
  4453 #ifdef MALLOC_FILL
  4454 	if (opt_poison)
  4455 		memset(ptr, 0x5a, size);
  4456 #endif
  4458 	arena_run_reg_dalloc(run, bin, ptr, size);
  4459 	run->nfree++;
  4461 	if (run->nfree == bin->nregs) {
  4462 		/* Deallocate run. */
  4463 		if (run == bin->runcur)
  4464 			bin->runcur = NULL;
  4465 		else if (bin->nregs != 1) {
  4466 			size_t run_pageind = (((uintptr_t)run -
  4467 			    (uintptr_t)chunk)) >> pagesize_2pow;
  4468 			arena_chunk_map_t *run_mapelm =
  4469 			    &chunk->map[run_pageind];
  4470 			/*
  4471 			 * This block's conditional is necessary because if the
  4472 			 * run only contains one region, then it never gets
  4473 			 * inserted into the non-full runs tree.
  4474 			 */
  4475 			RELEASE_ASSERT(arena_run_tree_search(&bin->runs, run_mapelm) ==
  4476 				run_mapelm);
  4477 			arena_run_tree_remove(&bin->runs, run_mapelm);
  4479 #if defined(MALLOC_DEBUG) || defined(MOZ_JEMALLOC_HARD_ASSERTS)
  4480 		run->magic = 0;
  4481 #endif
  4482 		VALGRIND_FREELIKE_BLOCK(run, 0);
  4483 		arena_run_dalloc(arena, run, true);
  4484 #ifdef MALLOC_STATS
  4485 		bin->stats.curruns--;
  4486 #endif
  4487 	} else if (run->nfree == 1 && run != bin->runcur) {
  4488 		/*
  4489 		 * Make sure that bin->runcur always refers to the lowest
  4490 		 * non-full run, if one exists.
  4491 		 */
  4492 		if (bin->runcur == NULL)
  4493 			bin->runcur = run;
  4494 		else if ((uintptr_t)run < (uintptr_t)bin->runcur) {
  4495 			/* Switch runcur. */
  4496 			if (bin->runcur->nfree > 0) {
  4497 				arena_chunk_t *runcur_chunk =
  4498 				    (arena_chunk_t*)CHUNK_ADDR2BASE(bin->runcur);
  4499 				size_t runcur_pageind =
  4500 				    (((uintptr_t)bin->runcur -
  4501 				    (uintptr_t)runcur_chunk)) >> pagesize_2pow;
  4502 				arena_chunk_map_t *runcur_mapelm =
  4503 				    &runcur_chunk->map[runcur_pageind];
  4505 				/* Insert runcur. */
  4506 				RELEASE_ASSERT(arena_run_tree_search(&bin->runs,
  4507 				    runcur_mapelm) == NULL);
  4508 				arena_run_tree_insert(&bin->runs,
  4509 				    runcur_mapelm);
  4511 			bin->runcur = run;
  4512 		} else {
  4513 			size_t run_pageind = (((uintptr_t)run -
  4514 			    (uintptr_t)chunk)) >> pagesize_2pow;
  4515 			arena_chunk_map_t *run_mapelm =
  4516 			    &chunk->map[run_pageind];
  4518 			RELEASE_ASSERT(arena_run_tree_search(&bin->runs, run_mapelm) ==
  4519 			    NULL);
  4520 			arena_run_tree_insert(&bin->runs, run_mapelm);
  4523 #ifdef MALLOC_STATS
  4524 	arena->stats.allocated_small -= size;
  4525 	arena->stats.ndalloc_small++;
  4526 #endif
  4529 static void
  4530 arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
  4532 	/* Large allocation. */
  4533 	malloc_spin_lock(&arena->lock);
  4535 #ifdef MALLOC_FILL
  4536 #ifndef MALLOC_STATS
  4537 	if (opt_poison)
  4538 #endif
  4539 #endif
  4541 		size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >>
  4542 		    pagesize_2pow;
  4543 		size_t size = chunk->map[pageind].bits & ~pagesize_mask;
  4545 #ifdef MALLOC_FILL
  4546 #ifdef MALLOC_STATS
  4547 		if (opt_poison)
  4548 #endif
  4549 			memset(ptr, 0x5a, size);
  4550 #endif
  4551 #ifdef MALLOC_STATS
  4552 		arena->stats.allocated_large -= size;
  4553 #endif
  4555 #ifdef MALLOC_STATS
  4556 	arena->stats.ndalloc_large++;
  4557 #endif
  4559 	arena_run_dalloc(arena, (arena_run_t *)ptr, true);
  4560 	malloc_spin_unlock(&arena->lock);
  4563 static inline void
  4564 arena_dalloc(void *ptr, size_t offset)
  4566 	arena_chunk_t *chunk;
  4567 	arena_t *arena;
  4568 	size_t pageind;
  4569 	arena_chunk_map_t *mapelm;
  4571 	assert(ptr != NULL);
  4572 	assert(offset != 0);
  4573 	assert(CHUNK_ADDR2OFFSET(ptr) == offset);
  4575 	chunk = (arena_chunk_t *) ((uintptr_t)ptr - offset);
  4576 	arena = chunk->arena;
  4577 	assert(arena != NULL);
  4578 	RELEASE_ASSERT(arena->magic == ARENA_MAGIC);
  4580 	pageind = offset >> pagesize_2pow;
  4581 	mapelm = &chunk->map[pageind];
  4582 	RELEASE_ASSERT((mapelm->bits & CHUNK_MAP_ALLOCATED) != 0);
  4583 	if ((mapelm->bits & CHUNK_MAP_LARGE) == 0) {
  4584 		/* Small allocation. */
  4585 		malloc_spin_lock(&arena->lock);
  4586 		arena_dalloc_small(arena, chunk, ptr, mapelm);
  4587 		malloc_spin_unlock(&arena->lock);
  4588 	} else
  4589 		arena_dalloc_large(arena, chunk, ptr);
  4590 	VALGRIND_FREELIKE_BLOCK(ptr, 0);
  4593 static inline void
  4594 idalloc(void *ptr)
  4596 	size_t offset;
  4598 	assert(ptr != NULL);
  4600 	offset = CHUNK_ADDR2OFFSET(ptr);
  4601 	if (offset != 0)
  4602 		arena_dalloc(ptr, offset);
  4603 	else
  4604 		huge_dalloc(ptr);
  4607 static void
  4608 arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
  4609     size_t size, size_t oldsize)
  4612 	assert(size < oldsize);
  4614 	/*
  4615 	 * Shrink the run, and make trailing pages available for other
  4616 	 * allocations.
  4617 	 */
  4618 #ifdef MALLOC_BALANCE
  4619 	arena_lock_balance(arena);
  4620 #else
  4621 	malloc_spin_lock(&arena->lock);
  4622 #endif
  4623 	arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size,
  4624 	    true);
  4625 #ifdef MALLOC_STATS
  4626 	arena->stats.allocated_large -= oldsize - size;
  4627 #endif
  4628 	malloc_spin_unlock(&arena->lock);
  4631 static bool
  4632 arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
  4633     size_t size, size_t oldsize)
  4635 	size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> pagesize_2pow;
  4636 	size_t npages = oldsize >> pagesize_2pow;
  4638 	RELEASE_ASSERT(oldsize == (chunk->map[pageind].bits & ~pagesize_mask));
  4640 	/* Try to extend the run. */
  4641 	assert(size > oldsize);
  4642 #ifdef MALLOC_BALANCE
  4643 	arena_lock_balance(arena);
  4644 #else
  4645 	malloc_spin_lock(&arena->lock);
  4646 #endif
  4647 	if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits
  4648 	    & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits &
  4649 	    ~pagesize_mask) >= size - oldsize) {
  4650 		/*
  4651 		 * The next run is available and sufficiently large.  Split the
  4652 		 * following run, then merge the first part with the existing
  4653 		 * allocation.
  4654 		 */
  4655 		arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk +
  4656 		    ((pageind+npages) << pagesize_2pow)), size - oldsize, true,
  4657 		    false);
  4659 		chunk->map[pageind].bits = size | CHUNK_MAP_LARGE |
  4660 		    CHUNK_MAP_ALLOCATED;
  4661 		chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE |
  4662 		    CHUNK_MAP_ALLOCATED;
  4664 #ifdef MALLOC_STATS
  4665 		arena->stats.allocated_large += size - oldsize;
  4666 #endif
  4667 		malloc_spin_unlock(&arena->lock);
  4668 		return (false);
  4670 	malloc_spin_unlock(&arena->lock);
  4672 	return (true);
  4675 /*
  4676  * Try to resize a large allocation, in order to avoid copying.  This will
  4677  * always fail if growing an object, and the following run is already in use.
  4678  */
  4679 static bool
  4680 arena_ralloc_large(void *ptr, size_t size, size_t oldsize)
  4682 	size_t psize;
  4684 	psize = PAGE_CEILING(size);
  4685 	if (psize == oldsize) {
  4686 		/* Same size class. */
  4687 #ifdef MALLOC_FILL
  4688 		if (opt_poison && size < oldsize) {
  4689 			memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize -
  4690 			    size);
  4692 #endif
  4693 		return (false);
  4694 	} else {
  4695 		arena_chunk_t *chunk;
  4696 		arena_t *arena;
  4698 		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
  4699 		arena = chunk->arena;
  4700 		RELEASE_ASSERT(arena->magic == ARENA_MAGIC);
  4702 		if (psize < oldsize) {
  4703 #ifdef MALLOC_FILL
  4704 			/* Fill before shrinking in order avoid a race. */
  4705 			if (opt_poison) {
  4706 				memset((void *)((uintptr_t)ptr + size), 0x5a,
  4707 				    oldsize - size);
  4709 #endif
  4710 			arena_ralloc_large_shrink(arena, chunk, ptr, psize,
  4711 			    oldsize);
  4712 			return (false);
  4713 		} else {
  4714 			bool ret = arena_ralloc_large_grow(arena, chunk, ptr,
  4715 			    psize, oldsize);
  4716 #ifdef MALLOC_FILL
  4717 			if (ret == false && opt_zero) {
  4718 				memset((void *)((uintptr_t)ptr + oldsize), 0,
  4719 				    size - oldsize);
  4721 #endif
  4722 			return (ret);
  4727 static void *
  4728 arena_ralloc(void *ptr, size_t size, size_t oldsize)
  4730 	void *ret;
  4731 	size_t copysize;
  4733 	/* Try to avoid moving the allocation. */
  4734 	if (size < small_min) {
  4735 		if (oldsize < small_min &&
  4736 		    ffs((int)(pow2_ceil(size) >> (TINY_MIN_2POW + 1)))
  4737 		    == ffs((int)(pow2_ceil(oldsize) >> (TINY_MIN_2POW + 1))))
  4738 			goto IN_PLACE; /* Same size class. */
  4739 	} else if (size <= small_max) {
  4740 		if (oldsize >= small_min && oldsize <= small_max &&
  4741 		    (QUANTUM_CEILING(size) >> opt_quantum_2pow)
  4742 		    == (QUANTUM_CEILING(oldsize) >> opt_quantum_2pow))
  4743 			goto IN_PLACE; /* Same size class. */
  4744 	} else if (size <= bin_maxclass) {
  4745 		if (oldsize > small_max && oldsize <= bin_maxclass &&
  4746 		    pow2_ceil(size) == pow2_ceil(oldsize))
  4747 			goto IN_PLACE; /* Same size class. */
  4748 	} else if (oldsize > bin_maxclass && oldsize <= arena_maxclass) {
  4749 		assert(size > bin_maxclass);
  4750 		if (arena_ralloc_large(ptr, size, oldsize) == false)
  4751 			return (ptr);
  4754 	/*
  4755 	 * If we get here, then size and oldsize are different enough that we
  4756 	 * need to move the object.  In that case, fall back to allocating new
  4757 	 * space and copying.
  4758 	 */
  4759 	ret = arena_malloc(choose_arena(), size, false);
  4760 	if (ret == NULL)
  4761 		return (NULL);
  4763 	/* Junk/zero-filling were already done by arena_malloc(). */
  4764 	copysize = (size < oldsize) ? size : oldsize;
  4765 #ifdef VM_COPY_MIN
  4766 	if (copysize >= VM_COPY_MIN)
  4767 		pages_copy(ret, ptr, copysize);
  4768 	else
  4769 #endif
  4770 		memcpy(ret, ptr, copysize);
  4771 	idalloc(ptr);
  4772 	return (ret);
  4773 IN_PLACE:
  4774 #ifdef MALLOC_FILL
  4775 	if (opt_poison && size < oldsize)
  4776 		memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size);
  4777 	else if (opt_zero && size > oldsize)
  4778 		memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize);
  4779 #endif
  4780 	return (ptr);
  4783 static inline void *
  4784 iralloc(void *ptr, size_t size)
  4786 	size_t oldsize;
  4788 	assert(ptr != NULL);
  4789 	assert(size != 0);
  4791 	oldsize = isalloc(ptr);
  4793 #ifndef MALLOC_VALGRIND
  4794 	if (size <= arena_maxclass)
  4795 		return (arena_ralloc(ptr, size, oldsize));
  4796 	else
  4797 		return (huge_ralloc(ptr, size, oldsize));
  4798 #else
  4799 	/*
  4800 	 * Valgrind does not provide a public interface for modifying an
  4801 	 * existing allocation, so use malloc/memcpy/free instead.
  4802 	 */
  4804 		void *ret = imalloc(size);
  4805 		if (ret != NULL) {
  4806 			if (oldsize < size)
  4807 			    memcpy(ret, ptr, oldsize);
  4808 			else
  4809 			    memcpy(ret, ptr, size);
  4810 			idalloc(ptr);
  4812 		return (ret);
  4814 #endif
  4817 static bool
  4818 arena_new(arena_t *arena)
  4820 	unsigned i;
  4821 	arena_bin_t *bin;
  4822 	size_t pow2_size, prev_run_size;
  4824 	if (malloc_spin_init(&arena->lock))
  4825 		return (true);
  4827 #ifdef MALLOC_STATS
  4828 	memset(&arena->stats, 0, sizeof(arena_stats_t));
  4829 #endif
  4831 	/* Initialize chunks. */
  4832 	arena_chunk_tree_dirty_new(&arena->chunks_dirty);
  4833 #ifdef MALLOC_DOUBLE_PURGE
  4834 	LinkedList_Init(&arena->chunks_madvised);
  4835 #endif
  4836 	arena->spare = NULL;
  4838 	arena->ndirty = 0;
  4840 	arena_avail_tree_new(&arena->runs_avail);
  4842 #ifdef MALLOC_BALANCE
  4843 	arena->contention = 0;
  4844 #endif
  4846 	/* Initialize bins. */
  4847 	prev_run_size = pagesize;
  4849 	/* (2^n)-spaced tiny bins. */
  4850 	for (i = 0; i < ntbins; i++) {
  4851 		bin = &arena->bins[i];
  4852 		bin->runcur = NULL;
  4853 		arena_run_tree_new(&bin->runs);
  4855 		bin->reg_size = (1U << (TINY_MIN_2POW + i));
  4857 		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
  4859 #ifdef MALLOC_STATS
  4860 		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
  4861 #endif
  4864 	/* Quantum-spaced bins. */
  4865 	for (; i < ntbins + nqbins; i++) {
  4866 		bin = &arena->bins[i];
  4867 		bin->runcur = NULL;
  4868 		arena_run_tree_new(&bin->runs);
  4870 		bin->reg_size = quantum * (i - ntbins + 1);
  4872 		pow2_size = pow2_ceil(quantum * (i - ntbins + 1));
  4873 		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
  4875 #ifdef MALLOC_STATS
  4876 		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
  4877 #endif
  4880 	/* (2^n)-spaced sub-page bins. */
  4881 	for (; i < ntbins + nqbins + nsbins; i++) {
  4882 		bin = &arena->bins[i];
  4883 		bin->runcur = NULL;
  4884 		arena_run_tree_new(&bin->runs);
  4886 		bin->reg_size = (small_max << (i - (ntbins + nqbins) + 1));
  4888 		prev_run_size = arena_bin_run_size_calc(bin, prev_run_size);
  4890 #ifdef MALLOC_STATS
  4891 		memset(&bin->stats, 0, sizeof(malloc_bin_stats_t));
  4892 #endif
  4895 #if defined(MALLOC_DEBUG) || defined(MOZ_JEMALLOC_HARD_ASSERTS)
  4896 	arena->magic = ARENA_MAGIC;
  4897 #endif
  4899 	return (false);
  4902 /* Create a new arena and insert it into the arenas array at index ind. */
  4903 static arena_t *
  4904 arenas_extend(unsigned ind)
  4906 	arena_t *ret;
  4908 	/* Allocate enough space for trailing bins. */
  4909 	ret = (arena_t *)base_alloc(sizeof(arena_t)
  4910 	    + (sizeof(arena_bin_t) * (ntbins + nqbins + nsbins - 1)));
  4911 	if (ret != NULL && arena_new(ret) == false) {
  4912 		arenas[ind] = ret;
  4913 		return (ret);
  4915 	/* Only reached if there is an OOM error. */
  4917 	/*
  4918 	 * OOM here is quite inconvenient to propagate, since dealing with it
  4919 	 * would require a check for failure in the fast path.  Instead, punt
  4920 	 * by using arenas[0].  In practice, this is an extremely unlikely
  4921 	 * failure.
  4922 	 */
  4923 	_malloc_message(_getprogname(),
  4924 	    ": (malloc) Error initializing arena\n", "", "");
  4925 	if (opt_abort)
  4926 		abort();
  4928 	return (arenas[0]);
  4931 /*
  4932  * End arena.
  4933  */
  4934 /******************************************************************************/
  4935 /*
  4936  * Begin general internal functions.
  4937  */
  4939 static void *
  4940 huge_malloc(size_t size, bool zero)
  4942 	void *ret;
  4943 	size_t csize;
  4944 	size_t psize;
  4945 	extent_node_t *node;
  4947 	/* Allocate one or more contiguous chunks for this request. */
  4949 	csize = CHUNK_CEILING(size);
  4950 	if (csize == 0) {
  4951 		/* size is large enough to cause size_t wrap-around. */
  4952 		return (NULL);
  4955 	/* Allocate an extent node with which to track the chunk. */
  4956 	node = base_node_alloc();
  4957 	if (node == NULL)
  4958 		return (NULL);
  4960 	ret = chunk_alloc(csize, zero, true);
  4961 	if (ret == NULL) {
  4962 		base_node_dealloc(node);
  4963 		return (NULL);
  4966 	/* Insert node into huge. */
  4967 	node->addr = ret;
  4968 	psize = PAGE_CEILING(size);
  4969 	node->size = psize;
  4971 	malloc_mutex_lock(&huge_mtx);
  4972 	extent_tree_ad_insert(&huge, node);
  4973 #ifdef MALLOC_STATS
  4974 	huge_nmalloc++;
  4976         /* Although we allocated space for csize bytes, we indicate that we've
  4977          * allocated only psize bytes.
  4979          * If DECOMMIT is defined, this is a reasonable thing to do, since
  4980          * we'll explicitly decommit the bytes in excess of psize.
  4982          * If DECOMMIT is not defined, then we're relying on the OS to be lazy
  4983          * about how it allocates physical pages to mappings.  If we never
  4984          * touch the pages in excess of psize, the OS won't allocate a physical
  4985          * page, and we won't use more than psize bytes of physical memory.
  4987          * A correct program will only touch memory in excess of how much it
  4988          * requested if it first calls malloc_usable_size and finds out how
  4989          * much space it has to play with.  But because we set node->size =
  4990          * psize above, malloc_usable_size will return psize, not csize, and
  4991          * the program will (hopefully) never touch bytes in excess of psize.
  4992          * Thus those bytes won't take up space in physical memory, and we can
  4993          * reasonably claim we never "allocated" them in the first place. */
  4994 	huge_allocated += psize;
  4995 	huge_mapped += csize;
  4996 #endif
  4997 	malloc_mutex_unlock(&huge_mtx);
  4999 #ifdef MALLOC_DECOMMIT
  5000 	if (csize - psize > 0)
  5001 		pages_decommit((void *)((uintptr_t)ret + psize), csize - psize);
  5002 #endif
  5004 #ifdef MALLOC_DECOMMIT
  5005 	VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, zero);
  5006 #else
  5007 	VALGRIND_MALLOCLIKE_BLOCK(ret, csize, 0, zero);
  5008 #endif
  5010 #ifdef MALLOC_FILL
  5011 	if (zero == false) {
  5012 		if (opt_junk)
  5013 #  ifdef MALLOC_DECOMMIT
  5014 			memset(ret, 0xa5, psize);
  5015 #  else
  5016 			memset(ret, 0xa5, csize);
  5017 #  endif
  5018 		else if (opt_zero)
  5019 #  ifdef MALLOC_DECOMMIT
  5020 			memset(ret, 0, psize);
  5021 #  else
  5022 			memset(ret, 0, csize);
  5023 #  endif
  5025 #endif
  5027 	return (ret);
  5030 /* Only handles large allocations that require more than chunk alignment. */
  5031 static void *
  5032 huge_palloc(size_t alignment, size_t size)
  5034 	void *ret;
  5035 	size_t alloc_size, chunk_size, offset;
  5036 	size_t psize;
  5037 	extent_node_t *node;
  5038 	int pfd;
  5040 	/*
  5041 	 * This allocation requires alignment that is even larger than chunk
  5042 	 * alignment.  This means that huge_malloc() isn't good enough.
  5044 	 * Allocate almost twice as many chunks as are demanded by the size or
  5045 	 * alignment, in order to assure the alignment can be achieved, then
  5046 	 * unmap leading and trailing chunks.
  5047 	 */
  5048 	assert(alignment >= chunksize);
  5050 	chunk_size = CHUNK_CEILING(size);
  5052 	if (size >= alignment)
  5053 		alloc_size = chunk_size + alignment - chunksize;
  5054 	else
  5055 		alloc_size = (alignment << 1) - chunksize;
  5057 	/* Allocate an extent node with which to track the chunk. */
  5058 	node = base_node_alloc();
  5059 	if (node == NULL)
  5060 		return (NULL);
  5062 	/*
  5063 	 * Windows requires that there be a 1:1 mapping between VM
  5064 	 * allocation/deallocation operations.  Therefore, take care here to
  5065 	 * acquire the final result via one mapping operation.
  5067 	 * The MALLOC_PAGEFILE code also benefits from this mapping algorithm,
  5068 	 * since it reduces the number of page files.
  5069 	 */
  5070 #ifdef MALLOC_PAGEFILE
  5071 	if (opt_pagefile) {
  5072 		pfd = pagefile_init(size);
  5073 		if (pfd == -1)
  5074 			return (NULL);
  5075 	} else
  5076 #endif
  5077 		pfd = -1;
  5078 #ifdef JEMALLOC_USES_MAP_ALIGN
  5079 		ret = pages_map_align(chunk_size, pfd, alignment);
  5080 #else
  5081 	do {
  5082 		void *over;
  5084 		over = chunk_alloc(alloc_size, false, false);
  5085 		if (over == NULL) {
  5086 			base_node_dealloc(node);
  5087 			ret = NULL;
  5088 			goto RETURN;
  5091 		offset = (uintptr_t)over & (alignment - 1);
  5092 		assert((offset & chunksize_mask) == 0);
  5093 		assert(offset < alloc_size);
  5094 		ret = (void *)((uintptr_t)over + offset);
  5095 		chunk_dealloc(over, alloc_size);
  5096 		ret = pages_map(ret, chunk_size, pfd);
  5097 		/*
  5098 		 * Failure here indicates a race with another thread, so try
  5099 		 * again.
  5100 		 */
  5101 	} while (ret == NULL);
  5102 #endif
  5103 	/* Insert node into huge. */
  5104 	node->addr = ret;
  5105 	psize = PAGE_CEILING(size);
  5106 	node->size = psize;
  5108 	malloc_mutex_lock(&huge_mtx);
  5109 	extent_tree_ad_insert(&huge, node);
  5110 #ifdef MALLOC_STATS
  5111 	huge_nmalloc++;
  5112         /* See note in huge_alloc() for why huge_allocated += psize is correct
  5113          * here even when DECOMMIT is not defined. */
  5114 	huge_allocated += psize;
  5115 	huge_mapped += chunk_size;
  5116 #endif
  5117 	malloc_mutex_unlock(&huge_mtx);
  5119 #ifdef MALLOC_DECOMMIT
  5120 	if (chunk_size - psize > 0) {
  5121 		pages_decommit((void *)((uintptr_t)ret + psize),
  5122 		    chunk_size - psize);
  5124 #endif
  5126 #ifdef MALLOC_DECOMMIT
  5127 	VALGRIND_MALLOCLIKE_BLOCK(ret, psize, 0, false);
  5128 #else
  5129 	VALGRIND_MALLOCLIKE_BLOCK(ret, chunk_size, 0, false);
  5130 #endif
  5132 #ifdef MALLOC_FILL
  5133 	if (opt_junk)
  5134 #  ifdef MALLOC_DECOMMIT
  5135 		memset(ret, 0xa5, psize);
  5136 #  else
  5137 		memset(ret, 0xa5, chunk_size);
  5138 #  endif
  5139 	else if (opt_zero)
  5140 #  ifdef MALLOC_DECOMMIT
  5141 		memset(ret, 0, psize);
  5142 #  else
  5143 		memset(ret, 0, chunk_size);
  5144 #  endif
  5145 #endif
  5147 RETURN:
  5148 #ifdef MALLOC_PAGEFILE
  5149 	if (pfd != -1)
  5150 		pagefile_close(pfd);
  5151 #endif
  5152 	return (ret);
  5155 static void *
  5156 huge_ralloc(void *ptr, size_t size, size_t oldsize)
  5158 	void *ret;
  5159 	size_t copysize;
  5161 	/* Avoid moving the allocation if the size class would not change. */
  5163 	if (oldsize > arena_maxclass &&
  5164 	    CHUNK_CEILING(size) == CHUNK_CEILING(oldsize)) {
  5165 		size_t psize = PAGE_CEILING(size);
  5166 #ifdef MALLOC_FILL
  5167 		if (opt_poison && size < oldsize) {
  5168 			memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize
  5169 			    - size);
  5171 #endif
  5172 #ifdef MALLOC_DECOMMIT
  5173 		if (psize < oldsize) {
  5174 			extent_node_t *node, key;
  5176 			pages_decommit((void *)((uintptr_t)ptr + psize),
  5177 			    oldsize - psize);
  5179 			/* Update recorded size. */
  5180 			malloc_mutex_lock(&huge_mtx);
  5181 			key.addr = __DECONST(void *, ptr);
  5182 			node = extent_tree_ad_search(&huge, &key);
  5183 			assert(node != NULL);
  5184 			assert(node->size == oldsize);
  5185 #  ifdef MALLOC_STATS
  5186 			huge_allocated -= oldsize - psize;
  5187 			/* No need to change huge_mapped, because we didn't
  5188 			 * (un)map anything. */
  5189 #  endif
  5190 			node->size = psize;
  5191 			malloc_mutex_unlock(&huge_mtx);
  5192 		} else if (psize > oldsize) {
  5193 			pages_commit((void *)((uintptr_t)ptr + oldsize),
  5194 			    psize - oldsize);
  5196 #endif
  5198                 /* Although we don't have to commit or decommit anything if
  5199                  * DECOMMIT is not defined and the size class didn't change, we
  5200                  * do need to update the recorded size if the size increased,
  5201                  * so malloc_usable_size doesn't return a value smaller than
  5202                  * what was requested via realloc(). */
  5204                 if (psize > oldsize) {
  5205                         /* Update recorded size. */
  5206                         extent_node_t *node, key;
  5207                         malloc_mutex_lock(&huge_mtx);
  5208                         key.addr = __DECONST(void *, ptr);
  5209                         node = extent_tree_ad_search(&huge, &key);
  5210                         assert(node != NULL);
  5211                         assert(node->size == oldsize);
  5212 #  ifdef MALLOC_STATS
  5213                         huge_allocated += psize - oldsize;
  5214 			/* No need to change huge_mapped, because we didn't
  5215 			 * (un)map anything. */
  5216 #  endif
  5217                         node->size = psize;
  5218                         malloc_mutex_unlock(&huge_mtx);
  5221 #ifdef MALLOC_FILL
  5222 		if (opt_zero && size > oldsize) {
  5223 			memset((void *)((uintptr_t)ptr + oldsize), 0, size
  5224 			    - oldsize);
  5226 #endif
  5227 		return (ptr);
  5230 	/*
  5231 	 * If we get here, then size and oldsize are different enough that we
  5232 	 * need to use a different size class.  In that case, fall back to
  5233 	 * allocating new space and copying.
  5234 	 */
  5235 	ret = huge_malloc(size, false);
  5236 	if (ret == NULL)
  5237 		return (NULL);
  5239 	copysize = (size < oldsize) ? size : oldsize;
  5240 #ifdef VM_COPY_MIN
  5241 	if (copysize >= VM_COPY_MIN)
  5242 		pages_copy(ret, ptr, copysize);
  5243 	else
  5244 #endif
  5245 		memcpy(ret, ptr, copysize);
  5246 	idalloc(ptr);
  5247 	return (ret);
  5250 static void
  5251 huge_dalloc(void *ptr)
  5253 	extent_node_t *node, key;
  5255 	malloc_mutex_lock(&huge_mtx);
  5257 	/* Extract from tree of huge allocations. */
  5258 	key.addr = ptr;
  5259 	node = extent_tree_ad_search(&huge, &key);
  5260 	assert(node != NULL);
  5261 	assert(node->addr == ptr);
  5262 	extent_tree_ad_remove(&huge, node);
  5264 #ifdef MALLOC_STATS
  5265 	huge_ndalloc++;
  5266 	huge_allocated -= node->size;
  5267 	huge_mapped -= CHUNK_CEILING(node->size);
  5268 #endif
  5270 	malloc_mutex_unlock(&huge_mtx);
  5272 	/* Unmap chunk. */
  5273 #ifdef MALLOC_FILL
  5274 	if (opt_junk)
  5275 		memset(node->addr, 0x5a, node->size);
  5276 #endif
  5277 	chunk_dealloc(node->addr, CHUNK_CEILING(node->size));
  5278 	VALGRIND_FREELIKE_BLOCK(node->addr, 0);
  5280 	base_node_dealloc(node);
  5283 #ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
  5284 #ifdef MOZ_MEMORY_BSD
  5285 static inline unsigned
  5286 malloc_ncpus(void)
  5288 	unsigned ret;
  5289 	int mib[2];
  5290 	size_t len;
  5292 	mib[0] = CTL_HW;
  5293 	mib[1] = HW_NCPU;
  5294 	len = sizeof(ret);
  5295 	if (sysctl(mib, 2, &ret, &len, (void *) 0, 0) == -1) {
  5296 		/* Error. */
  5297 		return (1);
  5300 	return (ret);
  5302 #elif (defined(MOZ_MEMORY_LINUX))
  5303 #include <fcntl.h>
  5305 static inline unsigned
  5306 malloc_ncpus(void)
  5308 	unsigned ret;
  5309 	int fd, nread, column;
  5310 	char buf[1024];
  5311 	static const char matchstr[] = "processor\t:";
  5312 	int i;
  5314 	/*
  5315 	 * sysconf(3) would be the preferred method for determining the number
  5316 	 * of CPUs, but it uses malloc internally, which causes untennable
  5317 	 * recursion during malloc initialization.
  5318 	 */
  5319 	fd = open("/proc/cpuinfo", O_RDONLY);
  5320 	if (fd == -1)
  5321 		return (1); /* Error. */
  5322 	/*
  5323 	 * Count the number of occurrences of matchstr at the beginnings of
  5324 	 * lines.  This treats hyperthreaded CPUs as multiple processors.
  5325 	 */
  5326 	column = 0;
  5327 	ret = 0;
  5328 	while (true) {
  5329 		nread = read(fd, &buf, sizeof(buf));
  5330 		if (nread <= 0)
  5331 			break; /* EOF or error. */
  5332 		for (i = 0;i < nread;i++) {
  5333 			char c = buf[i];
  5334 			if (c == '\n')
  5335 				column = 0;
  5336 			else if (column != -1) {
  5337 				if (c == matchstr[column]) {
  5338 					column++;
  5339 					if (column == sizeof(matchstr) - 1) {
  5340 						column = -1;
  5341 						ret++;
  5343 				} else
  5344 					column = -1;
  5349 	if (ret == 0)
  5350 		ret = 1; /* Something went wrong in the parser. */
  5351 	close(fd);
  5353 	return (ret);
  5355 #elif (defined(MOZ_MEMORY_DARWIN))
  5356 #include <mach/mach_init.h>
  5357 #include <mach/mach_host.h>
  5359 static inline unsigned
  5360 malloc_ncpus(void)
  5362 	kern_return_t error;
  5363 	natural_t n;
  5364 	processor_info_array_t pinfo;
  5365 	mach_msg_type_number_t pinfocnt;
  5367 	error = host_processor_info(mach_host_self(), PROCESSOR_BASIC_INFO,
  5368 				    &n, &pinfo, &pinfocnt);
  5369 	if (error != KERN_SUCCESS)
  5370 		return (1); /* Error. */
  5371 	else
  5372 		return (n);
  5374 #elif (defined(MOZ_MEMORY_SOLARIS))
  5376 static inline unsigned
  5377 malloc_ncpus(void)
  5379 	return sysconf(_SC_NPROCESSORS_ONLN);
  5381 #else
  5382 static inline unsigned
  5383 malloc_ncpus(void)
  5386 	/*
  5387 	 * We lack a way to determine the number of CPUs on this platform, so
  5388 	 * assume 1 CPU.
  5389 	 */
  5390 	return (1);
  5392 #endif
  5393 #endif
  5395 static void
  5396 malloc_print_stats(void)
  5399 	if (opt_print_stats) {
  5400 		char s[UMAX2S_BUFSIZE];
  5401 		_malloc_message("___ Begin malloc statistics ___\n", "", "",
  5402 		    "");
  5403 		_malloc_message("Assertions ",
  5404 #ifdef NDEBUG
  5405 		    "disabled",
  5406 #else
  5407 		    "enabled",
  5408 #endif
  5409 		    "\n", "");
  5410 		_malloc_message("Boolean MALLOC_OPTIONS: ",
  5411 		    opt_abort ? "A" : "a", "", "");
  5412 #ifdef MALLOC_FILL
  5413 		_malloc_message(opt_poison ? "C" : "c", "", "", "");
  5414 		_malloc_message(opt_junk ? "J" : "j", "", "", "");
  5415 #endif
  5416 #ifdef MALLOC_PAGEFILE
  5417 		_malloc_message(opt_pagefile ? "o" : "O", "", "", "");
  5418 #endif
  5419 		_malloc_message("P", "", "", "");
  5420 #ifdef MALLOC_UTRACE
  5421 		_malloc_message(opt_utrace ? "U" : "u", "", "", "");
  5422 #endif
  5423 #ifdef MALLOC_SYSV
  5424 		_malloc_message(opt_sysv ? "V" : "v", "", "", "");
  5425 #endif
  5426 #ifdef MALLOC_XMALLOC
  5427 		_malloc_message(opt_xmalloc ? "X" : "x", "", "", "");
  5428 #endif
  5429 #ifdef MALLOC_FILL
  5430 		_malloc_message(opt_zero ? "Z" : "z", "", "", "");
  5431 #endif
  5432 		_malloc_message("\n", "", "", "");
  5434 #ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
  5435 		_malloc_message("CPUs: ", umax2s(ncpus, 10, s), "\n", "");
  5436 #endif
  5437 		_malloc_message("Max arenas: ", umax2s(narenas, 10, s), "\n",
  5438 		    "");
  5439 #ifdef MALLOC_BALANCE
  5440 		_malloc_message("Arena balance threshold: ",
  5441 		    umax2s(opt_balance_threshold, 10, s), "\n", "");
  5442 #endif
  5443 		_malloc_message("Pointer size: ", umax2s(sizeof(void *), 10, s),
  5444 		    "\n", "");
  5445 		_malloc_message("Quantum size: ", umax2s(quantum, 10, s), "\n",
  5446 		    "");
  5447 		_malloc_message("Max small size: ", umax2s(small_max, 10, s),
  5448 		    "\n", "");
  5449 		_malloc_message("Max dirty pages per arena: ",
  5450 		    umax2s(opt_dirty_max, 10, s), "\n", "");
  5452 		_malloc_message("Chunk size: ", umax2s(chunksize, 10, s), "",
  5453 		    "");
  5454 		_malloc_message(" (2^", umax2s(opt_chunk_2pow, 10, s), ")\n",
  5455 		    "");
  5457 #ifdef MALLOC_STATS
  5459 			size_t allocated, mapped = 0;
  5460 #ifdef MALLOC_BALANCE
  5461 			uint64_t nbalance = 0;
  5462 #endif
  5463 			unsigned i;
  5464 			arena_t *arena;
  5466 			/* Calculate and print allocated/mapped stats. */
  5468 			/* arenas. */
  5469 			for (i = 0, allocated = 0; i < narenas; i++) {
  5470 				if (arenas[i] != NULL) {
  5471 					malloc_spin_lock(&arenas[i]->lock);
  5472 					allocated +=
  5473 					    arenas[i]->stats.allocated_small;
  5474 					allocated +=
  5475 					    arenas[i]->stats.allocated_large;
  5476 					mapped += arenas[i]->stats.mapped;
  5477 #ifdef MALLOC_BALANCE
  5478 					nbalance += arenas[i]->stats.nbalance;
  5479 #endif
  5480 					malloc_spin_unlock(&arenas[i]->lock);
  5484 			/* huge/base. */
  5485 			malloc_mutex_lock(&huge_mtx);
  5486 			allocated += huge_allocated;
  5487 			mapped += huge_mapped;
  5488 			malloc_mutex_unlock(&huge_mtx);
  5490 			malloc_mutex_lock(&base_mtx);
  5491 			mapped += base_mapped;
  5492 			malloc_mutex_unlock(&base_mtx);
  5494 #ifdef MOZ_MEMORY_WINDOWS
  5495 			malloc_printf("Allocated: %lu, mapped: %lu\n",
  5496 			    allocated, mapped);
  5497 #else
  5498 			malloc_printf("Allocated: %zu, mapped: %zu\n",
  5499 			    allocated, mapped);
  5500 #endif
  5502 #ifdef MALLOC_BALANCE
  5503 			malloc_printf("Arena balance reassignments: %llu\n",
  5504 			    nbalance);
  5505 #endif
  5507 			/* Print chunk stats. */
  5508 			malloc_printf(
  5509 			    "huge: nmalloc      ndalloc    allocated\n");
  5510 #ifdef MOZ_MEMORY_WINDOWS
  5511 			malloc_printf(" %12llu %12llu %12lu\n",
  5512 			    huge_nmalloc, huge_ndalloc, huge_allocated);
  5513 #else
  5514 			malloc_printf(" %12llu %12llu %12zu\n",
  5515 			    huge_nmalloc, huge_ndalloc, huge_allocated);
  5516 #endif
  5517 			/* Print stats for each arena. */
  5518 			for (i = 0; i < narenas; i++) {
  5519 				arena = arenas[i];
  5520 				if (arena != NULL) {
  5521 					malloc_printf(
  5522 					    "\narenas[%u]:\n", i);
  5523 					malloc_spin_lock(&arena->lock);
  5524 					stats_print(arena);
  5525 					malloc_spin_unlock(&arena->lock);
  5529 #endif /* #ifdef MALLOC_STATS */
  5530 		_malloc_message("--- End malloc statistics ---\n", "", "", "");
  5534 /*
  5535  * FreeBSD's pthreads implementation calls malloc(3), so the malloc
  5536  * implementation has to take pains to avoid infinite recursion during
  5537  * initialization.
  5538  */
  5539 #if (defined(MOZ_MEMORY_WINDOWS) || defined(MOZ_MEMORY_DARWIN))
  5540 #define	malloc_init() false
  5541 #else
  5542 static inline bool
  5543 malloc_init(void)
  5546 	if (malloc_initialized == false)
  5547 		return (malloc_init_hard());
  5549 	return (false);
  5551 #endif
  5553 #if !defined(MOZ_MEMORY_WINDOWS)
  5554 static
  5555 #endif
  5556 bool
  5557 malloc_init_hard(void)
  5559 	unsigned i;
  5560 	char buf[PATH_MAX + 1];
  5561 	const char *opts;
  5562 	long result;
  5563 #ifndef MOZ_MEMORY_WINDOWS
  5564 	int linklen;
  5565 #endif
  5566 #ifdef MOZ_MEMORY_DARWIN
  5567     malloc_zone_t* default_zone;
  5568 #endif
  5570 #ifndef MOZ_MEMORY_WINDOWS
  5571 	malloc_mutex_lock(&init_lock);
  5572 #endif
  5574 	if (malloc_initialized) {
  5575 		/*
  5576 		 * Another thread initialized the allocator before this one
  5577 		 * acquired init_lock.
  5578 		 */
  5579 #ifndef MOZ_MEMORY_WINDOWS
  5580 		malloc_mutex_unlock(&init_lock);
  5581 #endif
  5582 		return (false);
  5585 #ifdef MOZ_MEMORY_WINDOWS
  5586 	/* get a thread local storage index */
  5587 	tlsIndex = TlsAlloc();
  5588 #endif
  5590 	/* Get page size and number of CPUs */
  5591 #ifdef MOZ_MEMORY_WINDOWS
  5593 		SYSTEM_INFO info;
  5595 		GetSystemInfo(&info);
  5596 		result = info.dwPageSize;
  5598 #ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
  5599 		ncpus = info.dwNumberOfProcessors;
  5600 #endif
  5602 #else
  5603 #ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
  5604 	ncpus = malloc_ncpus();
  5605 #endif
  5607 	result = sysconf(_SC_PAGESIZE);
  5608 	assert(result != -1);
  5609 #endif
  5611 	/* We assume that the page size is a power of 2. */
  5612 	assert(((result - 1) & result) == 0);
  5613 #ifdef MALLOC_STATIC_SIZES
  5614 	if (pagesize % (size_t) result) {
  5615 		_malloc_message(_getprogname(),
  5616 				"Compile-time page size does not divide the runtime one.\n",
  5617 				"", "");
  5618 		abort();
  5620 #else	
  5621 	pagesize = (size_t) result;
  5622 	pagesize_mask = (size_t) result - 1;
  5623 	pagesize_2pow = ffs((int)result) - 1;
  5624 #endif
  5626 #ifdef MALLOC_PAGEFILE
  5627 	/*
  5628 	 * Determine where to create page files.  It is insufficient to
  5629 	 * unconditionally use P_tmpdir (typically "/tmp"), since for some
  5630 	 * operating systems /tmp is a separate filesystem that is rather small.
  5631 	 * Therefore prefer, in order, the following locations:
  5633 	 * 1) MALLOC_TMPDIR
  5634 	 * 2) TMPDIR
  5635 	 * 3) P_tmpdir
  5636 	 */
  5638 		char *s;
  5639 		size_t slen;
  5640 		static const char suffix[] = "/jemalloc.XXXXXX";
  5642 		if ((s = getenv("MALLOC_TMPDIR")) == NULL && (s =
  5643 		    getenv("TMPDIR")) == NULL)
  5644 			s = P_tmpdir;
  5645 		slen = strlen(s);
  5646 		if (slen + sizeof(suffix) > sizeof(pagefile_templ)) {
  5647 			_malloc_message(_getprogname(),
  5648 			    ": (malloc) Page file path too long\n",
  5649 			    "", "");
  5650 			abort();
  5652 		memcpy(pagefile_templ, s, slen);
  5653 		memcpy(&pagefile_templ[slen], suffix, sizeof(suffix));
  5655 #endif
  5657 	for (i = 0; i < 3; i++) {
  5658 		unsigned j;
  5660 		/* Get runtime configuration. */
  5661 		switch (i) {
  5662 		case 0:
  5663 #ifndef MOZ_MEMORY_WINDOWS
  5664 			if ((linklen = readlink("/etc/malloc.conf", buf,
  5665 						sizeof(buf) - 1)) != -1) {
  5666 				/*
  5667 				 * Use the contents of the "/etc/malloc.conf"
  5668 				 * symbolic link's name.
  5669 				 */
  5670 				buf[linklen] = '\0';
  5671 				opts = buf;
  5672 			} else
  5673 #endif
  5675 				/* No configuration specified. */
  5676 				buf[0] = '\0';
  5677 				opts = buf;
  5679 			break;
  5680 		case 1:
  5681 			if (issetugid() == 0 && (opts =
  5682 			    getenv("MALLOC_OPTIONS")) != NULL) {
  5683 				/*
  5684 				 * Do nothing; opts is already initialized to
  5685 				 * the value of the MALLOC_OPTIONS environment
  5686 				 * variable.
  5687 				 */
  5688 			} else {
  5689 				/* No configuration specified. */
  5690 				buf[0] = '\0';
  5691 				opts = buf;
  5693 			break;
  5694 		case 2:
  5695 			if (_malloc_options != NULL) {
  5696 				/*
  5697 				 * Use options that were compiled into the
  5698 				 * program.
  5699 				 */
  5700 				opts = _malloc_options;
  5701 			} else {
  5702 				/* No configuration specified. */
  5703 				buf[0] = '\0';
  5704 				opts = buf;
  5706 			break;
  5707 		default:
  5708 			/* NOTREACHED */
  5709 			buf[0] = '\0';
  5710 			opts = buf;
  5711 			assert(false);
  5714 		for (j = 0; opts[j] != '\0'; j++) {
  5715 			unsigned k, nreps;
  5716 			bool nseen;
  5718 			/* Parse repetition count, if any. */
  5719 			for (nreps = 0, nseen = false;; j++, nseen = true) {
  5720 				switch (opts[j]) {
  5721 					case '0': case '1': case '2': case '3':
  5722 					case '4': case '5': case '6': case '7':
  5723 					case '8': case '9':
  5724 						nreps *= 10;
  5725 						nreps += opts[j] - '0';
  5726 						break;
  5727 					default:
  5728 						goto MALLOC_OUT;
  5731 MALLOC_OUT:
  5732 			if (nseen == false)
  5733 				nreps = 1;
  5735 			for (k = 0; k < nreps; k++) {
  5736 				switch (opts[j]) {
  5737 				case 'a':
  5738 					opt_abort = false;
  5739 					break;
  5740 				case 'A':
  5741 					opt_abort = true;
  5742 					break;
  5743 				case 'b':
  5744 #ifdef MALLOC_BALANCE
  5745 					opt_balance_threshold >>= 1;
  5746 #endif
  5747 					break;
  5748 				case 'B':
  5749 #ifdef MALLOC_BALANCE
  5750 					if (opt_balance_threshold == 0)
  5751 						opt_balance_threshold = 1;
  5752 					else if ((opt_balance_threshold << 1)
  5753 					    > opt_balance_threshold)
  5754 						opt_balance_threshold <<= 1;
  5755 #endif
  5756 					break;
  5757 #ifdef MALLOC_FILL
  5758 #ifndef MALLOC_PRODUCTION
  5759 				case 'c':
  5760 					opt_poison = false;
  5761 					break;
  5762 				case 'C':
  5763 					opt_poison = true;
  5764 					break;
  5765 #endif
  5766 #endif
  5767 				case 'f':
  5768 					opt_dirty_max >>= 1;
  5769 					break;
  5770 				case 'F':
  5771 					if (opt_dirty_max == 0)
  5772 						opt_dirty_max = 1;
  5773 					else if ((opt_dirty_max << 1) != 0)
  5774 						opt_dirty_max <<= 1;
  5775 					break;
  5776 #ifdef MALLOC_FILL
  5777 #ifndef MALLOC_PRODUCTION
  5778 				case 'j':
  5779 					opt_junk = false;
  5780 					break;
  5781 				case 'J':
  5782 					opt_junk = true;
  5783 					break;
  5784 #endif
  5785 #endif
  5786 #ifndef MALLOC_STATIC_SIZES
  5787 				case 'k':
  5788 					/*
  5789 					 * Chunks always require at least one
  5790 					 * header page, so chunks can never be
  5791 					 * smaller than two pages.
  5792 					 */
  5793 					if (opt_chunk_2pow > pagesize_2pow + 1)
  5794 						opt_chunk_2pow--;
  5795 					break;
  5796 				case 'K':
  5797 					if (opt_chunk_2pow + 1 <
  5798 					    (sizeof(size_t) << 3))
  5799 						opt_chunk_2pow++;
  5800 					break;
  5801 #endif
  5802 				case 'n':
  5803 					opt_narenas_lshift--;
  5804 					break;
  5805 				case 'N':
  5806 					opt_narenas_lshift++;
  5807 					break;
  5808 #ifdef MALLOC_PAGEFILE
  5809 				case 'o':
  5810 					/* Do not over-commit. */
  5811 					opt_pagefile = true;
  5812 					break;
  5813 				case 'O':
  5814 					/* Allow over-commit. */
  5815 					opt_pagefile = false;
  5816 					break;
  5817 #endif
  5818 				case 'p':
  5819 					opt_print_stats = false;
  5820 					break;
  5821 				case 'P':
  5822 					opt_print_stats = true;
  5823 					break;
  5824 #ifndef MALLOC_STATIC_SIZES
  5825 				case 'q':
  5826 					if (opt_quantum_2pow > QUANTUM_2POW_MIN)
  5827 						opt_quantum_2pow--;
  5828 					break;
  5829 				case 'Q':
  5830 					if (opt_quantum_2pow < pagesize_2pow -
  5831 					    1)
  5832 						opt_quantum_2pow++;
  5833 					break;
  5834 				case 's':
  5835 					if (opt_small_max_2pow >
  5836 					    QUANTUM_2POW_MIN)
  5837 						opt_small_max_2pow--;
  5838 					break;
  5839 				case 'S':
  5840 					if (opt_small_max_2pow < pagesize_2pow
  5841 					    - 1)
  5842 						opt_small_max_2pow++;
  5843 					break;
  5844 #endif
  5845 #ifdef MALLOC_UTRACE
  5846 				case 'u':
  5847 					opt_utrace = false;
  5848 					break;
  5849 				case 'U':
  5850 					opt_utrace = true;
  5851 					break;
  5852 #endif
  5853 #ifdef MALLOC_SYSV
  5854 				case 'v':
  5855 					opt_sysv = false;
  5856 					break;
  5857 				case 'V':
  5858 					opt_sysv = true;
  5859 					break;
  5860 #endif
  5861 #ifdef MALLOC_XMALLOC
  5862 				case 'x':
  5863 					opt_xmalloc = false;
  5864 					break;
  5865 				case 'X':
  5866 					opt_xmalloc = true;
  5867 					break;
  5868 #endif
  5869 #ifdef MALLOC_FILL
  5870 #ifndef MALLOC_PRODUCTION
  5871 				case 'z':
  5872 					opt_zero = false;
  5873 					break;
  5874 				case 'Z':
  5875 					opt_zero = true;
  5876 					break;
  5877 #endif
  5878 #endif
  5879 				default: {
  5880 					char cbuf[2];
  5882 					cbuf[0] = opts[j];
  5883 					cbuf[1] = '\0';
  5884 					_malloc_message(_getprogname(),
  5885 					    ": (malloc) Unsupported character "
  5886 					    "in malloc options: '", cbuf,
  5887 					    "'\n");
  5894 	/* Take care to call atexit() only once. */
  5895 	if (opt_print_stats) {
  5896 #ifndef MOZ_MEMORY_WINDOWS
  5897 		/* Print statistics at exit. */
  5898 		atexit(malloc_print_stats);
  5899 #endif
  5902 #if !defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN)
  5903 	/* Prevent potential deadlock on malloc locks after fork. */
  5904 	pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork);
  5905 #endif
  5907 #ifndef MALLOC_STATIC_SIZES
  5908 	/* Set variables according to the value of opt_small_max_2pow. */
  5909 	if (opt_small_max_2pow < opt_quantum_2pow)
  5910 		opt_small_max_2pow = opt_quantum_2pow;
  5911 	small_max = (1U << opt_small_max_2pow);
  5913 	/* Set bin-related variables. */
  5914 	bin_maxclass = (pagesize >> 1);
  5915 	assert(opt_quantum_2pow >= TINY_MIN_2POW);
  5916 	ntbins = opt_quantum_2pow - TINY_MIN_2POW;
  5917 	assert(ntbins <= opt_quantum_2pow);
  5918 	nqbins = (small_max >> opt_quantum_2pow);
  5919 	nsbins = pagesize_2pow - opt_small_max_2pow - 1;
  5921 	/* Set variables according to the value of opt_quantum_2pow. */
  5922 	quantum = (1U << opt_quantum_2pow);
  5923 	quantum_mask = quantum - 1;
  5924 	if (ntbins > 0)
  5925 		small_min = (quantum >> 1) + 1;
  5926 	else
  5927 		small_min = 1;
  5928 	assert(small_min <= quantum);
  5930 	/* Set variables according to the value of opt_chunk_2pow. */
  5931 	chunksize = (1LU << opt_chunk_2pow);
  5932 	chunksize_mask = chunksize - 1;
  5933 	chunk_npages = (chunksize >> pagesize_2pow);
  5935 	arena_chunk_header_npages = calculate_arena_header_pages();
  5936 	arena_maxclass = calculate_arena_maxclass();
  5937 #endif
  5939 #ifdef JEMALLOC_USES_MAP_ALIGN
  5940 	/*
  5941 	 * When using MAP_ALIGN, the alignment parameter must be a power of two
  5942 	 * multiple of the system pagesize, or mmap will fail.
  5943 	 */
  5944 	assert((chunksize % pagesize) == 0);
  5945 	assert((1 << (ffs(chunksize / pagesize) - 1)) == (chunksize/pagesize));
  5946 #endif
  5948 	UTRACE(0, 0, 0);
  5950 	/* Various sanity checks that regard configuration. */
  5951 	assert(quantum >= sizeof(void *));
  5952 	assert(quantum <= pagesize);
  5953 	assert(chunksize >= pagesize);
  5954 	assert(quantum * 4 <= chunksize);
  5956 	/* Initialize chunks data. */
  5957 	malloc_mutex_init(&huge_mtx);
  5958 	extent_tree_ad_new(&huge);
  5959 #ifdef MALLOC_STATS
  5960 	huge_nmalloc = 0;
  5961 	huge_ndalloc = 0;
  5962 	huge_allocated = 0;
  5963 	huge_mapped = 0;
  5964 #endif
  5966 	/* Initialize base allocation data structures. */
  5967 #ifdef MALLOC_STATS
  5968 	base_mapped = 0;
  5969 	base_committed = 0;
  5970 #endif
  5971 	base_nodes = NULL;
  5972 	malloc_mutex_init(&base_mtx);
  5974 #ifdef MOZ_MEMORY_NARENAS_DEFAULT_ONE
  5975 	narenas = 1;
  5976 #else
  5977 	if (ncpus > 1) {
  5978 		/*
  5979 		 * For SMP systems, create four times as many arenas as there
  5980 		 * are CPUs by default.
  5981 		 */
  5982 		opt_narenas_lshift += 2;
  5985 	/* Determine how many arenas to use. */
  5986 	narenas = ncpus;
  5987 #endif
  5988 	if (opt_narenas_lshift > 0) {
  5989 		if ((narenas << opt_narenas_lshift) > narenas)
  5990 			narenas <<= opt_narenas_lshift;
  5991 		/*
  5992 		 * Make sure not to exceed the limits of what base_alloc() can
  5993 		 * handle.
  5994 		 */
  5995 		if (narenas * sizeof(arena_t *) > chunksize)
  5996 			narenas = chunksize / sizeof(arena_t *);
  5997 	} else if (opt_narenas_lshift < 0) {
  5998 		if ((narenas >> -opt_narenas_lshift) < narenas)
  5999 			narenas >>= -opt_narenas_lshift;
  6000 		/* Make sure there is at least one arena. */
  6001 		if (narenas == 0)
  6002 			narenas = 1;
  6004 #ifdef MALLOC_BALANCE
  6005 	assert(narenas != 0);
  6006 	for (narenas_2pow = 0;
  6007 	     (narenas >> (narenas_2pow + 1)) != 0;
  6008 	     narenas_2pow++);
  6009 #endif
  6011 #ifdef NO_TLS
  6012 	if (narenas > 1) {
  6013 		static const unsigned primes[] = {1, 3, 5, 7, 11, 13, 17, 19,
  6014 		    23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
  6015 		    89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
  6016 		    151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
  6017 		    223, 227, 229, 233, 239, 241, 251, 257, 263};
  6018 		unsigned nprimes, parenas;
  6020 		/*
  6021 		 * Pick a prime number of hash arenas that is more than narenas
  6022 		 * so that direct hashing of pthread_self() pointers tends to
  6023 		 * spread allocations evenly among the arenas.
  6024 		 */
  6025 		assert((narenas & 1) == 0); /* narenas must be even. */
  6026 		nprimes = (sizeof(primes) >> SIZEOF_INT_2POW);
  6027 		parenas = primes[nprimes - 1]; /* In case not enough primes. */
  6028 		for (i = 1; i < nprimes; i++) {
  6029 			if (primes[i] > narenas) {
  6030 				parenas = primes[i];
  6031 				break;
  6034 		narenas = parenas;
  6036 #endif
  6038 #ifndef NO_TLS
  6039 #  ifndef MALLOC_BALANCE
  6040 	next_arena = 0;
  6041 #  endif
  6042 #endif
  6044 	/* Allocate and initialize arenas. */
  6045 	arenas = (arena_t **)base_alloc(sizeof(arena_t *) * narenas);
  6046 	if (arenas == NULL) {
  6047 #ifndef MOZ_MEMORY_WINDOWS
  6048 		malloc_mutex_unlock(&init_lock);
  6049 #endif
  6050 		return (true);
  6052 	/*
  6053 	 * Zero the array.  In practice, this should always be pre-zeroed,
  6054 	 * since it was just mmap()ed, but let's be sure.
  6055 	 */
  6056 	memset(arenas, 0, sizeof(arena_t *) * narenas);
  6058 	/*
  6059 	 * Initialize one arena here.  The rest are lazily created in
  6060 	 * choose_arena_hard().
  6061 	 */
  6062 	arenas_extend(0);
  6063 	if (arenas[0] == NULL) {
  6064 #ifndef MOZ_MEMORY_WINDOWS
  6065 		malloc_mutex_unlock(&init_lock);
  6066 #endif
  6067 		return (true);
  6069 #ifndef NO_TLS
  6070 	/*
  6071 	 * Assign the initial arena to the initial thread, in order to avoid
  6072 	 * spurious creation of an extra arena if the application switches to
  6073 	 * threaded mode.
  6074 	 */
  6075 #ifdef MOZ_MEMORY_WINDOWS
  6076 	TlsSetValue(tlsIndex, arenas[0]);
  6077 #else
  6078 	arenas_map = arenas[0];
  6079 #endif
  6080 #endif
  6082 	/*
  6083 	 * Seed here for the initial thread, since choose_arena_hard() is only
  6084 	 * called for other threads.  The seed value doesn't really matter.
  6085 	 */
  6086 #ifdef MALLOC_BALANCE
  6087 	SPRN(balance, 42);
  6088 #endif
  6090 	malloc_spin_init(&arenas_lock);
  6092 #ifdef MALLOC_VALIDATE
  6093 	chunk_rtree = malloc_rtree_new((SIZEOF_PTR << 3) - opt_chunk_2pow);
  6094 	if (chunk_rtree == NULL)
  6095 		return (true);
  6096 #endif
  6098 	malloc_initialized = true;
  6100 #if defined(NEEDS_PTHREAD_MMAP_UNALIGNED_TSD)
  6101 	if (pthread_key_create(&mmap_unaligned_tsd, NULL) != 0) {
  6102 		malloc_printf("<jemalloc>: Error in pthread_key_create()\n");
  6104 #endif
  6106 #if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC)
  6107 	/*
  6108 	* Overwrite the default memory allocator to use jemalloc everywhere.
  6109 	*/
  6110 	default_zone = malloc_default_zone();
  6112 	/*
  6113 	 * We only use jemalloc with MacOS 10.6 and 10.7.  jemalloc is disabled
  6114 	 * on 32-bit builds (10.5 and 32-bit 10.6) due to bug 702250, an
  6115 	 * apparent MacOS bug.  In fact, this code isn't even compiled on
  6116 	 * 32-bit builds.
  6118 	 * We'll have to update our code to work with newer versions, because
  6119 	 * the malloc zone layout is likely to change.
  6120 	 */
  6122 	osx_use_jemalloc = (default_zone->version == SNOW_LEOPARD_MALLOC_ZONE_T_VERSION ||
  6123 			    default_zone->version == LION_MALLOC_ZONE_T_VERSION);
  6125 	/* Allow us dynamically turn off jemalloc for testing. */
  6126 	if (getenv("NO_MAC_JEMALLOC")) {
  6127 		osx_use_jemalloc = false;
  6128 #ifdef __i386__
  6129 		malloc_printf("Warning: NO_MAC_JEMALLOC has no effect on "
  6130 			      "i386 machines (such as this one).\n");
  6131 #endif
  6134 	if (osx_use_jemalloc) {
  6135 		/*
  6136 		 * Convert the default szone to an "overlay zone" that is capable
  6137 		 * of deallocating szone-allocated objects, but allocating new
  6138 		 * objects from jemalloc.
  6139 		 */
  6140 		size_t size = zone_version_size(default_zone->version);
  6141 		szone2ozone(default_zone, size);
  6143 	else {
  6144 		szone = default_zone;
  6146 #endif
  6148 #ifndef MOZ_MEMORY_WINDOWS
  6149 	malloc_mutex_unlock(&init_lock);
  6150 #endif
  6151 	return (false);
  6154 /* XXX Why not just expose malloc_print_stats()? */
  6155 #ifdef MOZ_MEMORY_WINDOWS
  6156 void
  6157 malloc_shutdown()
  6160 	malloc_print_stats();
  6162 #endif
  6164 /*
  6165  * End general internal functions.
  6166  */
  6167 /******************************************************************************/
  6168 /*
  6169  * Begin malloc(3)-compatible functions.
  6170  */
  6172 /*
  6173  * Even though we compile with MOZ_MEMORY, we may have to dynamically decide
  6174  * not to use jemalloc, as discussed above. However, we call jemalloc
  6175  * functions directly from mozalloc. Since it's pretty dangerous to mix the
  6176  * allocators, we need to call the OSX allocators from the functions below,
  6177  * when osx_use_jemalloc is not (dynamically) set.
  6179  * Note that we assume jemalloc is enabled on i386.  This is safe because the
  6180  * only i386 versions of MacOS are 10.5 and 10.6, which we support.  We have to
  6181  * do this because madvise isn't in the malloc zone struct for 10.5.
  6183  * This means that NO_MAC_JEMALLOC doesn't work on i386.
  6184  */
  6185 #if defined(MOZ_MEMORY_DARWIN) && !defined(__i386__) && !defined(MOZ_REPLACE_MALLOC)
  6186 #define DARWIN_ONLY(A) if (!osx_use_jemalloc) { A; }
  6187 #else
  6188 #define DARWIN_ONLY(A)
  6189 #endif
  6191 MOZ_MEMORY_API void *
  6192 malloc_impl(size_t size)
  6194 	void *ret;
  6196 	DARWIN_ONLY(return (szone->malloc)(szone, size));
  6198 	if (malloc_init()) {
  6199 		ret = NULL;
  6200 		goto RETURN;
  6203 	if (size == 0) {
  6204 #ifdef MALLOC_SYSV
  6205 		if (opt_sysv == false)
  6206 #endif
  6207 			size = 1;
  6208 #ifdef MALLOC_SYSV
  6209 		else {
  6210 			ret = NULL;
  6211 			goto RETURN;
  6213 #endif
  6216 	ret = imalloc(size);
  6218 RETURN:
  6219 	if (ret == NULL) {
  6220 #ifdef MALLOC_XMALLOC
  6221 		if (opt_xmalloc) {
  6222 			_malloc_message(_getprogname(),
  6223 			    ": (malloc) Error in malloc(): out of memory\n", "",
  6224 			    "");
  6225 			abort();
  6227 #endif
  6228 		errno = ENOMEM;
  6231 	UTRACE(0, size, ret);
  6232 	return (ret);
  6235 /*
  6236  * In ELF systems the default visibility allows symbols to be preempted at
  6237  * runtime. This in turn prevents the uses of memalign in this file from being
  6238  * optimized. What we do in here is define two aliasing symbols (they point to
  6239  * the same code): memalign and memalign_internal. The internal version has
  6240  * hidden visibility and is used in every reference from this file.
  6242  * For more information on this technique, see section 2.2.7 (Avoid Using
  6243  * Exported Symbols) in http://www.akkadia.org/drepper/dsohowto.pdf.
  6244  */
  6246 #ifndef MOZ_REPLACE_MALLOC
  6247 #if defined(__GNUC__) && !defined(MOZ_MEMORY_DARWIN)
  6248 #define MOZ_MEMORY_ELF
  6249 #endif
  6251 #ifdef MOZ_MEMORY_SOLARIS
  6252 #  ifdef __SUNPRO_C
  6253 void *
  6254 memalign_impl(size_t alignment, size_t size);
  6255 #pragma no_inline(memalign_impl)
  6256 #  elif (defined(__GNUC__))
  6257 __attribute__((noinline))
  6258 #  endif
  6259 #else
  6260 #if (defined(MOZ_MEMORY_ELF))
  6261 __attribute__((visibility ("hidden")))
  6262 #endif
  6263 #endif
  6264 #endif /* MOZ_REPLACE_MALLOC */
  6266 #ifdef MOZ_MEMORY_ELF
  6267 #define MEMALIGN memalign_internal
  6268 #else
  6269 #define MEMALIGN memalign_impl
  6270 #endif
  6272 #ifndef MOZ_MEMORY_ELF
  6273 MOZ_MEMORY_API
  6274 #endif
  6275 void *
  6276 MEMALIGN(size_t alignment, size_t size)
  6278 	void *ret;
  6280 	DARWIN_ONLY(return (szone->memalign)(szone, alignment, size));
  6282 	assert(((alignment - 1) & alignment) == 0);
  6284 	if (malloc_init()) {
  6285 		ret = NULL;
  6286 		goto RETURN;
  6289 	if (size == 0) {
  6290 #ifdef MALLOC_SYSV
  6291 		if (opt_sysv == false)
  6292 #endif
  6293 			size = 1;
  6294 #ifdef MALLOC_SYSV
  6295 		else {
  6296 			ret = NULL;
  6297 			goto RETURN;
  6299 #endif
  6302 	alignment = alignment < sizeof(void*) ? sizeof(void*) : alignment;
  6303 	ret = ipalloc(alignment, size);
  6305 RETURN:
  6306 #ifdef MALLOC_XMALLOC
  6307 	if (opt_xmalloc && ret == NULL) {
  6308 		_malloc_message(_getprogname(),
  6309 		": (malloc) Error in memalign(): out of memory\n", "", "");
  6310 		abort();
  6312 #endif
  6313 	UTRACE(0, size, ret);
  6314 	return (ret);
  6317 #ifdef MOZ_MEMORY_ELF
  6318 extern void *
  6319 memalign_impl(size_t alignment, size_t size) __attribute__((alias ("memalign_internal"), visibility ("default")));
  6320 #endif
  6322 MOZ_MEMORY_API int
  6323 posix_memalign_impl(void **memptr, size_t alignment, size_t size)
  6325 	void *result;
  6327 	/* Make sure that alignment is a large enough power of 2. */
  6328 	if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *)) {
  6329 #ifdef MALLOC_XMALLOC
  6330 		if (opt_xmalloc) {
  6331 			_malloc_message(_getprogname(),
  6332 			    ": (malloc) Error in posix_memalign(): "
  6333 			    "invalid alignment\n", "", "");
  6334 			abort();
  6336 #endif
  6337 		return (EINVAL);
  6340 	/* The 0-->1 size promotion is done in the memalign() call below */
  6342 	result = MEMALIGN(alignment, size);
  6344 	if (result == NULL)
  6345 		return (ENOMEM);
  6347 	*memptr = result;
  6348 	return (0);
  6351 MOZ_MEMORY_API void *
  6352 aligned_alloc_impl(size_t alignment, size_t size)
  6354 	if (size % alignment) {
  6355 #ifdef MALLOC_XMALLOC
  6356 		if (opt_xmalloc) {
  6357 			_malloc_message(_getprogname(),
  6358 			    ": (malloc) Error in aligned_alloc(): "
  6359 			    "size is not multiple of alignment\n", "", "");
  6360 			abort();
  6362 #endif
  6363 		return (NULL);
  6365 	return MEMALIGN(alignment, size);
  6368 MOZ_MEMORY_API void *
  6369 valloc_impl(size_t size)
  6371 	return (MEMALIGN(pagesize, size));
  6374 MOZ_MEMORY_API void *
  6375 calloc_impl(size_t num, size_t size)
  6377 	void *ret;
  6378 	size_t num_size;
  6380 	DARWIN_ONLY(return (szone->calloc)(szone, num, size));
  6382 	if (malloc_init()) {
  6383 		num_size = 0;
  6384 		ret = NULL;
  6385 		goto RETURN;
  6388 	num_size = num * size;
  6389 	if (num_size == 0) {
  6390 #ifdef MALLOC_SYSV
  6391 		if ((opt_sysv == false) && ((num == 0) || (size == 0)))
  6392 #endif
  6393 			num_size = 1;
  6394 #ifdef MALLOC_SYSV
  6395 		else {
  6396 			ret = NULL;
  6397 			goto RETURN;
  6399 #endif
  6400 	/*
  6401 	 * Try to avoid division here.  We know that it isn't possible to
  6402 	 * overflow during multiplication if neither operand uses any of the
  6403 	 * most significant half of the bits in a size_t.
  6404 	 */
  6405 	} else if (((num | size) & (SIZE_T_MAX << (sizeof(size_t) << 2)))
  6406 	    && (num_size / size != num)) {
  6407 		/* size_t overflow. */
  6408 		ret = NULL;
  6409 		goto RETURN;
  6412 	ret = icalloc(num_size);
  6414 RETURN:
  6415 	if (ret == NULL) {
  6416 #ifdef MALLOC_XMALLOC
  6417 		if (opt_xmalloc) {
  6418 			_malloc_message(_getprogname(),
  6419 			    ": (malloc) Error in calloc(): out of memory\n", "",
  6420 			    "");
  6421 			abort();
  6423 #endif
  6424 		errno = ENOMEM;
  6427 	UTRACE(0, num_size, ret);
  6428 	return (ret);
  6431 MOZ_MEMORY_API void *
  6432 realloc_impl(void *ptr, size_t size)
  6434 	void *ret;
  6436 	DARWIN_ONLY(return (szone->realloc)(szone, ptr, size));
  6438 	if (size == 0) {
  6439 #ifdef MALLOC_SYSV
  6440 		if (opt_sysv == false)
  6441 #endif
  6442 			size = 1;
  6443 #ifdef MALLOC_SYSV
  6444 		else {
  6445 			if (ptr != NULL)
  6446 				idalloc(ptr);
  6447 			ret = NULL;
  6448 			goto RETURN;
  6450 #endif
  6453 	if (ptr != NULL) {
  6454 		assert(malloc_initialized);
  6456 		ret = iralloc(ptr, size);
  6458 		if (ret == NULL) {
  6459 #ifdef MALLOC_XMALLOC
  6460 			if (opt_xmalloc) {
  6461 				_malloc_message(_getprogname(),
  6462 				    ": (malloc) Error in realloc(): out of "
  6463 				    "memory\n", "", "");
  6464 				abort();
  6466 #endif
  6467 			errno = ENOMEM;
  6469 	} else {
  6470 		if (malloc_init())
  6471 			ret = NULL;
  6472 		else
  6473 			ret = imalloc(size);
  6475 		if (ret == NULL) {
  6476 #ifdef MALLOC_XMALLOC
  6477 			if (opt_xmalloc) {
  6478 				_malloc_message(_getprogname(),
  6479 				    ": (malloc) Error in realloc(): out of "
  6480 				    "memory\n", "", "");
  6481 				abort();
  6483 #endif
  6484 			errno = ENOMEM;
  6488 #ifdef MALLOC_SYSV
  6489 RETURN:
  6490 #endif
  6491 	UTRACE(ptr, size, ret);
  6492 	return (ret);
  6495 MOZ_MEMORY_API void
  6496 free_impl(void *ptr)
  6498 	size_t offset;
  6500 	DARWIN_ONLY((szone->free)(szone, ptr); return);
  6502 	UTRACE(ptr, 0, 0);
  6504 	/*
  6505 	 * A version of idalloc that checks for NULL pointer but only for
  6506 	 * huge allocations assuming that CHUNK_ADDR2OFFSET(NULL) == 0.
  6507 	 */
  6508 	assert(CHUNK_ADDR2OFFSET(NULL) == 0);
  6509 	offset = CHUNK_ADDR2OFFSET(ptr);
  6510 	if (offset != 0)
  6511 		arena_dalloc(ptr, offset);
  6512 	else if (ptr != NULL)
  6513 		huge_dalloc(ptr);
  6516 /*
  6517  * End malloc(3)-compatible functions.
  6518  */
  6519 /******************************************************************************/
  6520 /*
  6521  * Begin non-standard functions.
  6522  */
  6524 /* This was added by Mozilla for use by SQLite. */
  6525 #if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC)
  6526 static
  6527 #else
  6528 MOZ_MEMORY_API
  6529 #endif
  6530 size_t
  6531 malloc_good_size_impl(size_t size)
  6533 	/*
  6534 	 * This duplicates the logic in imalloc(), arena_malloc() and
  6535 	 * arena_malloc_small().
  6536 	 */
  6537 	if (size < small_min) {
  6538 		/* Small (tiny). */
  6539 		size = pow2_ceil(size);
  6540 		/*
  6541 		 * We omit the #ifdefs from arena_malloc_small() --
  6542 		 * it can be inaccurate with its size in some cases, but this
  6543 		 * function must be accurate.
  6544 		 */
  6545 		if (size < (1U << TINY_MIN_2POW))
  6546 			size = (1U << TINY_MIN_2POW);
  6547 	} else if (size <= small_max) {
  6548 		/* Small (quantum-spaced). */
  6549 		size = QUANTUM_CEILING(size);
  6550 	} else if (size <= bin_maxclass) {
  6551 		/* Small (sub-page). */
  6552 		size = pow2_ceil(size);
  6553 	} else if (size <= arena_maxclass) {
  6554 		/* Large. */
  6555 		size = PAGE_CEILING(size);
  6556 	} else {
  6557 		/*
  6558 		 * Huge.  We use PAGE_CEILING to get psize, instead of using
  6559 		 * CHUNK_CEILING to get csize.  This ensures that this
  6560 		 * malloc_usable_size(malloc(n)) always matches
  6561 		 * malloc_good_size(n).
  6562 		 */
  6563 		size = PAGE_CEILING(size);
  6565 	return size;
  6569 #if defined(MOZ_MEMORY_ANDROID) && (ANDROID_VERSION < 19)
  6570 MOZ_MEMORY_API size_t
  6571 malloc_usable_size_impl(void *ptr)
  6572 #else
  6573 MOZ_MEMORY_API size_t
  6574 malloc_usable_size_impl(const void *ptr)
  6575 #endif
  6577 	DARWIN_ONLY(return (szone->size)(szone, ptr));
  6579 #ifdef MALLOC_VALIDATE
  6580 	return (isalloc_validate(ptr));
  6581 #else
  6582 	assert(ptr != NULL);
  6584 	return (isalloc(ptr));
  6585 #endif
  6588 MOZ_JEMALLOC_API void
  6589 jemalloc_stats_impl(jemalloc_stats_t *stats)
  6591 	size_t i;
  6593 	assert(stats != NULL);
  6595 	/*
  6596 	 * Gather runtime settings.
  6597 	 */
  6598 	stats->opt_abort = opt_abort;
  6599 	stats->opt_junk =
  6600 #ifdef MALLOC_FILL
  6601 	    opt_junk ? true :
  6602 #endif
  6603 	    false;
  6604 	stats->opt_poison =
  6605 #ifdef MALLOC_FILL
  6606 	    opt_poison ? true :
  6607 #endif
  6608 	    false;
  6609 	stats->opt_utrace =
  6610 #ifdef MALLOC_UTRACE
  6611 	    opt_utrace ? true :
  6612 #endif
  6613 	    false;
  6614 	stats->opt_sysv =
  6615 #ifdef MALLOC_SYSV
  6616 	    opt_sysv ? true :
  6617 #endif
  6618 	    false;
  6619 	stats->opt_xmalloc =
  6620 #ifdef MALLOC_XMALLOC
  6621 	    opt_xmalloc ? true :
  6622 #endif
  6623 	    false;
  6624 	stats->opt_zero =
  6625 #ifdef MALLOC_FILL
  6626 	    opt_zero ? true :
  6627 #endif
  6628 	    false;
  6629 	stats->narenas = narenas;
  6630 	stats->balance_threshold =
  6631 #ifdef MALLOC_BALANCE
  6632 	    opt_balance_threshold
  6633 #else
  6634 	    SIZE_T_MAX
  6635 #endif
  6637 	stats->quantum = quantum;
  6638 	stats->small_max = small_max;
  6639 	stats->large_max = arena_maxclass;
  6640 	stats->chunksize = chunksize;
  6641 	stats->dirty_max = opt_dirty_max;
  6643 	/*
  6644 	 * Gather current memory usage statistics.
  6645 	 */
  6646 	stats->mapped = 0;
  6647 	stats->allocated = 0;
  6648         stats->waste = 0;
  6649 	stats->page_cache = 0;
  6650         stats->bookkeeping = 0;
  6652 	/* Get huge mapped/allocated. */
  6653 	malloc_mutex_lock(&huge_mtx);
  6654 	stats->mapped += huge_mapped;
  6655 	stats->allocated += huge_allocated;
  6656 	assert(huge_mapped >= huge_allocated);
  6657 	malloc_mutex_unlock(&huge_mtx);
  6659 	/* Get base mapped/allocated. */
  6660 	malloc_mutex_lock(&base_mtx);
  6661 	stats->mapped += base_mapped;
  6662 	stats->bookkeeping += base_committed;
  6663 	assert(base_mapped >= base_committed);
  6664 	malloc_mutex_unlock(&base_mtx);
  6666 	/* Iterate over arenas. */
  6667 	for (i = 0; i < narenas; i++) {
  6668 		arena_t *arena = arenas[i];
  6669 		size_t arena_mapped, arena_allocated, arena_committed, arena_dirty;
  6671 		if (arena == NULL) {
  6672 			continue;
  6675 		malloc_spin_lock(&arena->lock);
  6677 		arena_mapped = arena->stats.mapped;
  6679 		/* "committed" counts dirty and allocated memory. */
  6680 		arena_committed = arena->stats.committed << pagesize_2pow;
  6682 		arena_allocated = arena->stats.allocated_small +
  6683 				  arena->stats.allocated_large;
  6685 		arena_dirty = arena->ndirty << pagesize_2pow;
  6687 		malloc_spin_unlock(&arena->lock);
  6689 		assert(arena_mapped >= arena_committed);
  6690 		assert(arena_committed >= arena_allocated + arena_dirty);
  6692 		/* "waste" is committed memory that is neither dirty nor
  6693 		 * allocated. */
  6694 		stats->mapped += arena_mapped;
  6695 		stats->allocated += arena_allocated;
  6696 		stats->page_cache += arena_dirty;
  6697 		stats->waste += arena_committed - arena_allocated - arena_dirty;
  6700 	assert(stats->mapped >= stats->allocated + stats->waste +
  6701 				stats->page_cache + stats->bookkeeping);
  6704 #ifdef MALLOC_DOUBLE_PURGE
  6706 /* Explicitly remove all of this chunk's MADV_FREE'd pages from memory. */
  6707 static void
  6708 hard_purge_chunk(arena_chunk_t *chunk)
  6710 	/* See similar logic in arena_purge(). */
  6712 	size_t i;
  6713 	for (i = arena_chunk_header_npages; i < chunk_npages; i++) {
  6714 		/* Find all adjacent pages with CHUNK_MAP_MADVISED set. */
  6715 		size_t npages;
  6716 		for (npages = 0;
  6717 		     chunk->map[i + npages].bits & CHUNK_MAP_MADVISED && i + npages < chunk_npages;
  6718 		     npages++) {
  6719 			/* Turn off the chunk's MADV_FREED bit and turn on its
  6720 			 * DECOMMITTED bit. */
  6721 			RELEASE_ASSERT(!(chunk->map[i + npages].bits & CHUNK_MAP_DECOMMITTED));
  6722 			chunk->map[i + npages].bits ^= CHUNK_MAP_MADVISED_OR_DECOMMITTED;
  6725 		/* We could use mincore to find out which pages are actually
  6726 		 * present, but it's not clear that's better. */
  6727 		if (npages > 0) {
  6728 			pages_decommit(((char*)chunk) + (i << pagesize_2pow), npages << pagesize_2pow);
  6729 			pages_commit(((char*)chunk) + (i << pagesize_2pow), npages << pagesize_2pow);
  6731 		i += npages;
  6735 /* Explicitly remove all of this arena's MADV_FREE'd pages from memory. */
  6736 static void
  6737 hard_purge_arena(arena_t *arena)
  6739 	malloc_spin_lock(&arena->lock);
  6741 	while (!LinkedList_IsEmpty(&arena->chunks_madvised)) {
  6742 		LinkedList* next = arena->chunks_madvised.next;
  6743 		arena_chunk_t *chunk =
  6744 			LinkedList_Get(arena->chunks_madvised.next,
  6745 				       arena_chunk_t, chunks_madvised_elem);
  6746 		hard_purge_chunk(chunk);
  6747 		LinkedList_Remove(&chunk->chunks_madvised_elem);
  6750 	malloc_spin_unlock(&arena->lock);
  6753 MOZ_JEMALLOC_API void
  6754 jemalloc_purge_freed_pages_impl()
  6756 	size_t i;
  6757 	for (i = 0; i < narenas; i++) {
  6758 		arena_t *arena = arenas[i];
  6759 		if (arena != NULL)
  6760 			hard_purge_arena(arena);
  6764 #else /* !defined MALLOC_DOUBLE_PURGE */
  6766 MOZ_JEMALLOC_API void
  6767 jemalloc_purge_freed_pages_impl()
  6769 	/* Do nothing. */
  6772 #endif /* defined MALLOC_DOUBLE_PURGE */
  6776 #ifdef MOZ_MEMORY_WINDOWS
  6777 void*
  6778 _recalloc(void *ptr, size_t count, size_t size)
  6780 	size_t oldsize = (ptr != NULL) ? isalloc(ptr) : 0;
  6781 	size_t newsize = count * size;
  6783 	/*
  6784 	 * In order for all trailing bytes to be zeroed, the caller needs to
  6785 	 * use calloc(), followed by recalloc().  However, the current calloc()
  6786 	 * implementation only zeros the bytes requested, so if recalloc() is
  6787 	 * to work 100% correctly, calloc() will need to change to zero
  6788 	 * trailing bytes.
  6789 	 */
  6791 	ptr = realloc(ptr, newsize);
  6792 	if (ptr != NULL && oldsize < newsize) {
  6793 		memset((void *)((uintptr_t)ptr + oldsize), 0, newsize -
  6794 		    oldsize);
  6797 	return ptr;
  6800 /*
  6801  * This impl of _expand doesn't ever actually expand or shrink blocks: it
  6802  * simply replies that you may continue using a shrunk block.
  6803  */
  6804 void*
  6805 _expand(void *ptr, size_t newsize)
  6807 	if (isalloc(ptr) >= newsize)
  6808 		return ptr;
  6810 	return NULL;
  6813 size_t
  6814 _msize(const void *ptr)
  6817 	return malloc_usable_size_impl(ptr);
  6819 #endif
  6821 MOZ_JEMALLOC_API void
  6822 jemalloc_free_dirty_pages_impl(void)
  6824 	size_t i;
  6825 	for (i = 0; i < narenas; i++) {
  6826 		arena_t *arena = arenas[i];
  6828 		if (arena != NULL) {
  6829 			malloc_spin_lock(&arena->lock);
  6830 			arena_purge(arena, true);
  6831 			malloc_spin_unlock(&arena->lock);
  6836 /*
  6837  * End non-standard functions.
  6838  */
  6839 /******************************************************************************/
  6840 /*
  6841  * Begin library-private functions, used by threading libraries for protection
  6842  * of malloc during fork().  These functions are only called if the program is
  6843  * running in threaded mode, so there is no need to check whether the program
  6844  * is threaded here.
  6845  */
  6847 static void
  6848 _malloc_prefork(void)
  6850 	unsigned i;
  6852 	/* Acquire all mutexes in a safe order. */
  6854 	malloc_spin_lock(&arenas_lock);
  6855 	for (i = 0; i < narenas; i++) {
  6856 		if (arenas[i] != NULL)
  6857 			malloc_spin_lock(&arenas[i]->lock);
  6860 	malloc_mutex_lock(&base_mtx);
  6862 	malloc_mutex_lock(&huge_mtx);
  6865 static void
  6866 _malloc_postfork(void)
  6868 	unsigned i;
  6870 	/* Release all mutexes, now that fork() has completed. */
  6872 	malloc_mutex_unlock(&huge_mtx);
  6874 	malloc_mutex_unlock(&base_mtx);
  6876 	for (i = 0; i < narenas; i++) {
  6877 		if (arenas[i] != NULL)
  6878 			malloc_spin_unlock(&arenas[i]->lock);
  6880 	malloc_spin_unlock(&arenas_lock);
  6883 /*
  6884  * End library-private functions.
  6885  */
  6886 /******************************************************************************/
  6888 #ifdef HAVE_DLOPEN
  6889 #  include <dlfcn.h>
  6890 #endif
  6892 #if defined(MOZ_MEMORY_DARWIN)
  6894 #if !defined(MOZ_REPLACE_MALLOC)
  6895 static void *
  6896 zone_malloc(malloc_zone_t *zone, size_t size)
  6899 	return (malloc_impl(size));
  6902 static void *
  6903 zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
  6906 	return (calloc_impl(num, size));
  6909 static void *
  6910 zone_valloc(malloc_zone_t *zone, size_t size)
  6912 	void *ret = NULL; /* Assignment avoids useless compiler warning. */
  6914 	posix_memalign_impl(&ret, pagesize, size);
  6916 	return (ret);
  6919 static void *
  6920 zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
  6922 	return (memalign_impl(alignment, size));
  6925 static void *
  6926 zone_destroy(malloc_zone_t *zone)
  6929 	/* This function should never be called. */
  6930 	assert(false);
  6931 	return (NULL);
  6934 static size_t
  6935 zone_good_size(malloc_zone_t *zone, size_t size)
  6937 	return malloc_good_size_impl(size);
  6940 static size_t
  6941 ozone_size(malloc_zone_t *zone, void *ptr)
  6943 	size_t ret = isalloc_validate(ptr);
  6944 	if (ret == 0)
  6945 		ret = szone->size(zone, ptr);
  6947 	return ret;
  6950 static void
  6951 ozone_free(malloc_zone_t *zone, void *ptr)
  6953 	if (isalloc_validate(ptr) != 0)
  6954 		free_impl(ptr);
  6955 	else {
  6956 		size_t size = szone->size(zone, ptr);
  6957 		if (size != 0)
  6958 			(szone->free)(zone, ptr);
  6959 		/* Otherwise we leak. */
  6963 static void *
  6964 ozone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
  6966     size_t oldsize;
  6967 	if (ptr == NULL)
  6968 		return (malloc_impl(size));
  6970 	oldsize = isalloc_validate(ptr);
  6971 	if (oldsize != 0)
  6972 		return (realloc_impl(ptr, size));
  6973 	else {
  6974 		oldsize = szone->size(zone, ptr);
  6975 		if (oldsize == 0)
  6976 			return (malloc_impl(size));
  6977 		else {
  6978 			void *ret = malloc_impl(size);
  6979 			if (ret != NULL) {
  6980 				memcpy(ret, ptr, (oldsize < size) ? oldsize :
  6981 				    size);
  6982 				(szone->free)(zone, ptr);
  6984 			return (ret);
  6989 static unsigned
  6990 ozone_batch_malloc(malloc_zone_t *zone, size_t size, void **results,
  6991     unsigned num_requested)
  6993 	/* Don't bother implementing this interface, since it isn't required. */
  6994 	return 0;
  6997 static void
  6998 ozone_batch_free(malloc_zone_t *zone, void **to_be_freed, unsigned num)
  7000 	unsigned i;
  7002 	for (i = 0; i < num; i++)
  7003 		ozone_free(zone, to_be_freed[i]);
  7006 static void
  7007 ozone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
  7009 	if (isalloc_validate(ptr) != 0) {
  7010 		assert(isalloc_validate(ptr) == size);
  7011 		free_impl(ptr);
  7012 	} else {
  7013 		assert(size == szone->size(zone, ptr));
  7014 		l_szone.m16(zone, ptr, size);
  7018 static void
  7019 ozone_force_lock(malloc_zone_t *zone)
  7021 	_malloc_prefork();
  7022 	szone->introspect->force_lock(zone);
  7025 static void
  7026 ozone_force_unlock(malloc_zone_t *zone)
  7028 	szone->introspect->force_unlock(zone);
  7029         _malloc_postfork();
  7032 static size_t
  7033 zone_version_size(int version)
  7035     switch (version)
  7037         case SNOW_LEOPARD_MALLOC_ZONE_T_VERSION:
  7038             return sizeof(snow_leopard_malloc_zone);
  7039         case LEOPARD_MALLOC_ZONE_T_VERSION:
  7040             return sizeof(leopard_malloc_zone);
  7041         default:
  7042         case LION_MALLOC_ZONE_T_VERSION:
  7043             return sizeof(lion_malloc_zone);
  7047 /*
  7048  * Overlay the default scalable zone (szone) such that existing allocations are
  7049  * drained, and further allocations come from jemalloc. This is necessary
  7050  * because Core Foundation directly accesses and uses the szone before the
  7051  * jemalloc library is even loaded.
  7052  */
  7053 static void
  7054 szone2ozone(malloc_zone_t *default_zone, size_t size)
  7056     lion_malloc_zone *l_zone;
  7057 	assert(malloc_initialized);
  7059 	/*
  7060 	 * Stash a copy of the original szone so that we can call its
  7061 	 * functions as needed. Note that internally, the szone stores its
  7062 	 * bookkeeping data structures immediately following the malloc_zone_t
  7063 	 * header, so when calling szone functions, we need to pass a pointer to
  7064 	 * the original zone structure.
  7065 	 */
  7066 	memcpy(szone, default_zone, size);
  7068 	/* OSX 10.7 allocates the default zone in protected memory. */
  7069 	if (default_zone->version >= LION_MALLOC_ZONE_T_VERSION) {
  7070 		void* start_of_page = (void*)((size_t)(default_zone) & ~pagesize_mask);
  7071 		mprotect (start_of_page, size, PROT_READ | PROT_WRITE);
  7074 	default_zone->size = (void *)ozone_size;
  7075 	default_zone->malloc = (void *)zone_malloc;
  7076 	default_zone->calloc = (void *)zone_calloc;
  7077 	default_zone->valloc = (void *)zone_valloc;
  7078 	default_zone->free = (void *)ozone_free;
  7079 	default_zone->realloc = (void *)ozone_realloc;
  7080 	default_zone->destroy = (void *)zone_destroy;
  7081 	default_zone->batch_malloc = NULL;
  7082 	default_zone->batch_free = ozone_batch_free;
  7083 	default_zone->introspect = ozone_introspect;
  7085 	/* Don't modify default_zone->zone_name; Mac libc may rely on the name
  7086 	 * being unchanged.  See Mozilla bug 694896. */
  7088 	ozone_introspect->enumerator = NULL;
  7089 	ozone_introspect->good_size = (void *)zone_good_size;
  7090 	ozone_introspect->check = NULL;
  7091 	ozone_introspect->print = NULL;
  7092 	ozone_introspect->log = NULL;
  7093 	ozone_introspect->force_lock = (void *)ozone_force_lock;
  7094 	ozone_introspect->force_unlock = (void *)ozone_force_unlock;
  7095 	ozone_introspect->statistics = NULL;
  7097     /* Platform-dependent structs */
  7098     l_zone = (lion_malloc_zone*)(default_zone);
  7100     if (default_zone->version >= SNOW_LEOPARD_MALLOC_ZONE_T_VERSION) {
  7101         l_zone->m15 = (void (*)())zone_memalign;
  7102         l_zone->m16 = (void (*)())ozone_free_definite_size;
  7103         l_ozone_introspect.m9 = NULL;
  7106     if (default_zone->version >= LION_MALLOC_ZONE_T_VERSION) {
  7107         l_zone->m17 = NULL;
  7108         l_ozone_introspect.m10 = NULL;
  7109         l_ozone_introspect.m11 = NULL;
  7110         l_ozone_introspect.m12 = NULL;
  7111         l_ozone_introspect.m13 = NULL;
  7114 #endif
  7116 __attribute__((constructor))
  7117 void
  7118 jemalloc_darwin_init(void)
  7120 	if (malloc_init_hard())
  7121 		abort();
  7124 #endif
  7126 /*
  7127  * is_malloc(malloc_impl) is some macro magic to detect if malloc_impl is
  7128  * defined as "malloc" in mozmemory_wrap.h
  7129  */
  7130 #define malloc_is_malloc 1
  7131 #define is_malloc_(a) malloc_is_ ## a
  7132 #define is_malloc(a) is_malloc_(a)
  7134 #if !defined(MOZ_MEMORY_DARWIN) && (is_malloc(malloc_impl) == 1)
  7135 #  if defined(__GLIBC__) && !defined(__UCLIBC__)
  7136 /*
  7137  * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
  7138  * to inconsistently reference libc's malloc(3)-compatible functions
  7139  * (bug 493541).
  7141  * These definitions interpose hooks in glibc.  The functions are actually
  7142  * passed an extra argument for the caller return address, which will be
  7143  * ignored.
  7144  */
  7145 MOZ_MEMORY_API void (*__free_hook)(void *ptr) = free_impl;
  7146 MOZ_MEMORY_API void *(*__malloc_hook)(size_t size) = malloc_impl;
  7147 MOZ_MEMORY_API void *(*__realloc_hook)(void *ptr, size_t size) = realloc_impl;
  7148 MOZ_MEMORY_API void *(*__memalign_hook)(size_t alignment, size_t size) = MEMALIGN;
  7150 #  elif defined(RTLD_DEEPBIND)
  7151 /*
  7152  * XXX On systems that support RTLD_GROUP or DF_1_GROUP, do their
  7153  * implementations permit similar inconsistencies?  Should STV_SINGLETON
  7154  * visibility be used for interposition where available?
  7155  */
  7156 #    error "Interposing malloc is unsafe on this system without libc malloc hooks."
  7157 #  endif
  7158 #endif
  7160 #ifdef MOZ_MEMORY_WINDOWS
  7161 /*
  7162  * In the new style jemalloc integration jemalloc is built as a separate
  7163  * shared library.  Since we're no longer hooking into the CRT binary,
  7164  * we need to initialize the heap at the first opportunity we get.
  7165  * DLL_PROCESS_ATTACH in DllMain is that opportunity.
  7166  */
  7167 BOOL APIENTRY DllMain(HINSTANCE hModule, 
  7168                       DWORD reason, 
  7169                       LPVOID lpReserved)
  7171   switch (reason) {
  7172     case DLL_PROCESS_ATTACH:
  7173       /* Don't force the system to page DllMain back in every time
  7174        * we create/destroy a thread */
  7175       DisableThreadLibraryCalls(hModule);
  7176       /* Initialize the heap */
  7177       malloc_init_hard();
  7178       break;
  7180     case DLL_PROCESS_DETACH:
  7181       break;
  7185   return TRUE;
  7187 #endif

mercurial