Wed, 31 Dec 2014 06:09:35 +0100
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.
1021 *
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.
1053 *
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)); \
1344 }
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
1436 *
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.
1440 *
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.
1447 *
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.
1454 *
1455 *
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.
1460 *
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)
1504 {
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);
1530 }
1532 return (&s[i]);
1533 }
1535 static void
1536 wrtmessage(const char *p1, const char *p2, const char *p3, const char *p4)
1537 {
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));
1545 }
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()
1573 {
1574 MOZ_CRASH();
1575 }
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)
1596 {
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);
1611 }
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);
1622 }
1624 static inline void
1625 malloc_mutex_lock(malloc_mutex_t *mutex)
1626 {
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
1638 }
1640 static inline void
1641 malloc_mutex_unlock(malloc_mutex_t *mutex)
1642 {
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
1654 }
1656 static bool
1657 malloc_spin_init(malloc_spinlock_t *lock)
1658 {
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);
1673 }
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);
1682 }
1684 static inline void
1685 malloc_spin_lock(malloc_spinlock_t *lock)
1686 {
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
1698 }
1700 static inline void
1701 malloc_spin_unlock(malloc_spinlock_t *lock)
1702 {
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
1713 }
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))
1745 {
1747 return (0);
1748 }
1750 static bool
1751 malloc_spin_init(pthread_mutex_t *lock)
1752 {
1754 if (_pthread_mutex_init_calloc_cb(lock, base_calloc) != 0)
1755 return (true);
1757 return (false);
1758 }
1760 static inline unsigned
1761 malloc_spin_lock(pthread_mutex_t *lock)
1762 {
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);
1778 }
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);
1788 }
1789 }
1791 return (ret);
1792 }
1794 static inline void
1795 malloc_spin_unlock(pthread_mutex_t *lock)
1796 {
1798 if (isthreaded)
1799 _pthread_mutex_unlock(lock);
1800 }
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)
1838 {
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);
1851 }
1853 #ifdef MALLOC_BALANCE
1854 /*
1855 * Use a simple linear congruential pseudo-random number generator:
1856 *
1857 * prn(y) = (a*x + c) % m
1858 *
1859 * where the following constants ensure maximal period:
1860 *
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
1864 *
1865 * See Knuth's TAOCP 3rd Ed., Vol. 2, pg. 17 for details on these constraints.
1866 *
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 } \
1878 \
1879 static inline uint32_t \
1880 prn_##suffix(uint32_t lg_range) \
1881 { \
1882 uint32_t ret, x; \
1883 \
1884 assert(lg_range > 0); \
1885 assert(lg_range <= 32); \
1886 \
1887 x = (var * (a)) + (c); \
1888 var = x; \
1889 ret = x >> (32 - lg_range); \
1890 \
1891 return (ret); \
1892 }
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)
1906 {
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");
1943 }
1945 return (0);
1946 }
1947 #endif
1949 static inline const char *
1950 _getprogname(void)
1951 {
1953 return ("<jemalloc>");
1954 }
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, ...)
1962 {
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, "", "", "");
1970 }
1971 #endif
1973 /******************************************************************************/
1975 static inline void
1976 pages_decommit(void *addr, size_t size)
1977 {
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
1986 }
1988 static inline void
1989 pages_commit(void *addr, size_t size)
1990 {
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
2000 }
2002 static bool
2003 base_pages_alloc_mmap(size_t minsize)
2004 {
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;
2026 }
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);
2053 }
2055 static bool
2056 base_pages_alloc(size_t minsize)
2057 {
2059 if (base_pages_alloc_mmap(minsize) == false)
2060 return (false);
2062 return (true);
2063 }
2065 static void *
2066 base_alloc(size_t size)
2067 {
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);
2080 }
2081 }
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
2100 }
2101 #endif
2102 malloc_mutex_unlock(&base_mtx);
2103 VALGRIND_MALLOCLIKE_BLOCK(ret, size, 0, false);
2105 return (ret);
2106 }
2108 static void *
2109 base_calloc(size_t number, size_t size)
2110 {
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);
2118 }
2119 #endif
2120 memset(ret, 0, number * size);
2122 return (ret);
2123 }
2125 static extent_node_t *
2126 base_node_alloc(void)
2127 {
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));
2140 }
2142 return (ret);
2143 }
2145 static void
2146 base_node_dealloc(extent_node_t *node)
2147 {
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);
2155 }
2157 /******************************************************************************/
2159 #ifdef MALLOC_STATS
2160 static void
2161 stats_print(arena_t *arena)
2162 {
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);
2237 }
2238 gap_start = UINT_MAX;
2239 }
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);
2258 }
2259 }
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);
2267 }
2268 }
2269 }
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)
2282 {
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);
2293 }
2295 return (ret);
2296 }
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)
2304 {
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));
2309 }
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)
2327 {
2328 void *ret = NULL;
2329 ret = VirtualAlloc(addr, size, MEM_COMMIT | MEM_RESERVE,
2330 PAGE_READWRITE);
2331 return (ret);
2332 }
2334 static void
2335 pages_unmap(void *addr, size_t size)
2336 {
2337 if (VirtualFree(addr, 0, MEM_RELEASE) == 0) {
2338 _malloc_message(_getprogname(),
2339 ": (malloc) Error in VirtualFree()\n", "", "");
2340 if (opt_abort)
2341 abort();
2342 }
2343 }
2344 #else
2345 #ifdef JEMALLOC_USES_MAP_ALIGN
2346 static void *
2347 pages_map_align(size_t size, int pfd, size_t alignment)
2348 {
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
2361 {
2362 ret = mmap((void *)alignment, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
2363 MAP_NOSYNC | MAP_ALIGN | MAP_ANON, -1, 0);
2364 }
2365 assert(ret != NULL);
2367 if (ret == MAP_FAILED)
2368 ret = NULL;
2369 return (ret);
2370 }
2371 #endif
2373 static void *
2374 pages_map(void *addr, size_t size, int pfd)
2375 {
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.
2385 *
2386 * The addr is chosen as 0x0000070000000000, which still allows about 120TB of virtual
2387 * address space.
2388 *
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;
2395 }
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
2408 {
2409 ret = mmap(addr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE |
2410 MAP_ANON, -1, 0);
2411 }
2412 assert(ret != NULL);
2414 if (ret == MAP_FAILED) {
2415 ret = NULL;
2416 }
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;
2425 }
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();
2442 }
2443 ret = NULL;
2444 }
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);
2454 }
2456 static void
2457 pages_unmap(void *addr, size_t size)
2458 {
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();
2468 }
2469 }
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)
2476 {
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);
2484 }
2485 #endif
2487 #ifdef MALLOC_VALIDATE
2488 static inline malloc_rtree_t *
2489 malloc_rtree_new(unsigned bits)
2490 {
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);
2522 }
2524 return (ret);
2525 }
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; \
2536 \
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 } \
2549 \
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); \
2558 \
2559 MALLOC_RTREE_GET_VALIDATE \
2560 return (ret); \
2561 }
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)
2597 {
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);
2615 }
2616 node[subkey] = child;
2617 }
2618 }
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);
2627 }
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)
2636 {
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);
2684 }
2685 /*
2686 * Failure here indicates a race with another thread, so
2687 * try again.
2688 */
2689 }
2690 }
2691 RETURN:
2692 #endif
2693 #ifdef MALLOC_PAGEFILE
2694 if (pfd != -1)
2695 pagefile_close(pfd);
2696 #endif
2698 return (ret);
2699 }
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)
2716 {
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);
2728 }
2730 static void *
2731 chunk_alloc_mmap_slow(size_t size, size_t alignment)
2732 {
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);
2751 }
2753 static void *
2754 chunk_alloc_mmap(size_t size, bool pagefile)
2755 {
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().
2766 *
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));
2779 }
2781 assert(ret != NULL);
2782 return (ret);
2783 }
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)
2790 {
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();
2813 }
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();
2832 }
2833 pagefile_close(ret);
2834 return (-1);
2835 }
2836 }
2838 return (ret);
2839 }
2841 static void
2842 pagefile_close(int pfd)
2843 {
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();
2853 }
2854 }
2855 #endif
2857 static void *
2858 chunk_alloc(size_t size, bool zero, bool pagefile)
2859 {
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;
2868 }
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);
2879 }
2880 }
2881 #endif
2883 assert(CHUNK_ADDR2BASE(ret) == ret);
2884 return (ret);
2885 }
2887 static void
2888 chunk_dealloc_mmap(void *chunk, size_t size)
2889 {
2891 pages_unmap(chunk, size);
2892 }
2894 static void
2895 chunk_dealloc(void *chunk, size_t size)
2896 {
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);
2908 }
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)
2924 {
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]);
2936 }
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);
2947 }
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.
2970 *
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);
2987 }
2988 } else
2989 ret = arenas[0];
2990 #endif
2992 RELEASE_ASSERT(ret != NULL);
2993 return (ret);
2994 }
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)
3003 {
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);
3023 }
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);
3041 }
3042 #endif
3044 static inline int
3045 arena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b)
3046 {
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));
3054 }
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)
3062 {
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));
3070 }
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)
3078 {
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;
3095 }
3096 b_mapelm = (uintptr_t)b;
3098 ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm);
3099 }
3101 return (ret);
3102 }
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)
3110 {
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);
3138 }
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);
3162 }
3163 }
3164 /* Not reached. */
3165 RELEASE_ASSERT(0);
3166 return (NULL);
3167 }
3169 static inline void
3170 arena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size)
3171 {
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.
3175 *
3176 * X / D
3177 *
3178 * becomes
3179 *
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)
3194 ,
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.
3220 *
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;
3244 }
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
3269 }
3271 static void
3272 arena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large,
3273 bool zero)
3274 {
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]);
3301 }
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;
3327 }
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
3342 }
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. */
3362 }
3363 }
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. */
3370 }
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;
3379 }
3380 }
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);
3393 }
3395 static void
3396 arena_chunk_init(arena_t *arena, arena_chunk_t *chunk)
3397 {
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;
3422 }
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
3447 }
3449 static void
3450 arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
3451 {
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
3461 }
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
3474 }
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;
3485 }
3487 static arena_run_t *
3488 arena_run_alloc(arena_t *arena, arena_bin_t *bin, size_t size, bool large,
3489 bool zero)
3490 {
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);
3511 }
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);
3524 }
3526 /*
3527 * No usable runs. Create a new chunk from which to allocate
3528 * the run.
3529 */
3530 {
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));
3539 }
3540 /* Update page map. */
3541 arena_run_split(arena, run, size, large, zero);
3542 return (run);
3543 }
3545 static void
3546 arena_purge(arena_t *arena, bool all)
3547 {
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;
3600 }
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;
3631 }
3632 }
3634 if (chunk->ndirty == 0) {
3635 arena_chunk_tree_dirty_remove(&arena->chunks_dirty,
3636 chunk);
3637 }
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);
3644 }
3645 #endif
3646 }
3647 }
3649 static void
3650 arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty)
3651 {
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;
3674 }
3676 if (chunk->ndirty == 0) {
3677 arena_chunk_tree_dirty_insert(&arena->chunks_dirty,
3678 chunk);
3679 }
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);
3688 }
3689 }
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);
3717 }
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);
3742 }
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);
3755 }
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)
3760 {
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);
3776 }
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)
3781 {
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);
3798 }
3800 static arena_run_t *
3801 arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin)
3802 {
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);
3817 }
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));
3846 }
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);
3862 }
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)
3867 {
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);
3878 }
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)
3883 {
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));
3892 }
3894 /*
3895 * Calculate bin->run_size such that it meets the following constraints:
3896 *
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).
3901 *
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)
3907 {
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.
3920 *
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);
3975 }
3977 #ifdef MALLOC_BALANCE
3978 static inline void
3979 arena_lock_balance(arena_t *arena)
3980 {
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);
3995 }
3996 }
3998 static void
3999 arena_lock_balance_hard(arena_t *arena)
4000 {
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
4028 }
4029 malloc_spin_unlock(&arenas_lock);
4030 }
4031 }
4032 #endif
4034 static inline void *
4035 arena_malloc_small(arena_t *arena, size_t size, bool zero)
4036 {
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)];
4065 }
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);
4081 }
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);
4102 }
4104 static void *
4105 arena_malloc_large(arena_t *arena, size_t size, bool zero)
4106 {
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);
4120 }
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
4135 }
4137 return (ret);
4138 }
4140 static inline void *
4141 arena_malloc(arena_t *arena, size_t size, bool zero)
4142 {
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));
4153 }
4155 static inline void *
4156 imalloc(size_t size)
4157 {
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));
4165 }
4167 static inline void *
4168 icalloc(size_t size)
4169 {
4171 if (size <= arena_maxclass)
4172 return (arena_malloc(choose_arena(), size, true));
4173 else
4174 return (huge_malloc(size, true));
4175 }
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)
4180 {
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);
4197 }
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);
4214 }
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);
4222 }
4223 }
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);
4239 }
4241 static inline void *
4242 ipalloc(size_t alignment, size_t size)
4243 {
4244 void *ret;
4245 size_t ceil_size;
4247 /*
4248 * Round size up to the nearest multiple of alignment.
4249 *
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:
4254 *
4255 * Size | Base 2 | Minimum alignment
4256 * -----+----------+------------------
4257 * 96 | 1100000 | 32
4258 * 144 | 10100000 | 32
4259 * 192 | 11000000 | 64
4260 *
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);
4273 }
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.
4290 *
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);
4302 }
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;
4321 }
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);
4330 }
4332 assert(((uintptr_t)ret & (alignment - 1)) == 0);
4333 return (ret);
4334 }
4336 /* Return the size of the allocation pointed to by ptr. */
4337 static size_t
4338 arena_salloc(const void *ptr)
4339 {
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);
4358 }
4360 return (ret);
4361 }
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:
4367 *
4368 * + Check that ptr is not NULL.
4369 *
4370 * + Check that ptr lies within a mapped chunk.
4371 */
4372 static inline size_t
4373 isalloc_validate(const void *ptr)
4374 {
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);
4402 }
4403 }
4404 #endif
4406 static inline size_t
4407 isalloc(const void *ptr)
4408 {
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);
4435 }
4437 return (ret);
4438 }
4440 static inline void
4441 arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
4442 arena_chunk_map_t *mapelm)
4443 {
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);
4478 }
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);
4510 }
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);
4521 }
4522 }
4523 #ifdef MALLOC_STATS
4524 arena->stats.allocated_small -= size;
4525 arena->stats.ndalloc_small++;
4526 #endif
4527 }
4529 static void
4530 arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr)
4531 {
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
4540 {
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
4554 }
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);
4561 }
4563 static inline void
4564 arena_dalloc(void *ptr, size_t offset)
4565 {
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);
4591 }
4593 static inline void
4594 idalloc(void *ptr)
4595 {
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);
4605 }
4607 static void
4608 arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr,
4609 size_t size, size_t oldsize)
4610 {
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);
4629 }
4631 static bool
4632 arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr,
4633 size_t size, size_t oldsize)
4634 {
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);
4669 }
4670 malloc_spin_unlock(&arena->lock);
4672 return (true);
4673 }
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)
4681 {
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);
4691 }
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);
4708 }
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);
4720 }
4721 #endif
4722 return (ret);
4723 }
4724 }
4725 }
4727 static void *
4728 arena_ralloc(void *ptr, size_t size, size_t oldsize)
4729 {
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);
4752 }
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);
4781 }
4783 static inline void *
4784 iralloc(void *ptr, size_t size)
4785 {
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 */
4803 {
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);
4811 }
4812 return (ret);
4813 }
4814 #endif
4815 }
4817 static bool
4818 arena_new(arena_t *arena)
4819 {
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
4862 }
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
4878 }
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
4893 }
4895 #if defined(MALLOC_DEBUG) || defined(MOZ_JEMALLOC_HARD_ASSERTS)
4896 arena->magic = ARENA_MAGIC;
4897 #endif
4899 return (false);
4900 }
4902 /* Create a new arena and insert it into the arenas array at index ind. */
4903 static arena_t *
4904 arenas_extend(unsigned ind)
4905 {
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);
4914 }
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]);
4929 }
4931 /*
4932 * End arena.
4933 */
4934 /******************************************************************************/
4935 /*
4936 * Begin general internal functions.
4937 */
4939 static void *
4940 huge_malloc(size_t size, bool zero)
4941 {
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);
4953 }
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);
4964 }
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.
4978 *
4979 * If DECOMMIT is defined, this is a reasonable thing to do, since
4980 * we'll explicitly decommit the bytes in excess of psize.
4981 *
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.
4986 *
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
5024 }
5025 #endif
5027 return (ret);
5028 }
5030 /* Only handles large allocations that require more than chunk alignment. */
5031 static void *
5032 huge_palloc(size_t alignment, size_t size)
5033 {
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.
5043 *
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.
5066 *
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;
5089 }
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);
5123 }
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);
5153 }
5155 static void *
5156 huge_ralloc(void *ptr, size_t size, size_t oldsize)
5157 {
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);
5170 }
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);
5195 }
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);
5219 }
5221 #ifdef MALLOC_FILL
5222 if (opt_zero && size > oldsize) {
5223 memset((void *)((uintptr_t)ptr + oldsize), 0, size
5224 - oldsize);
5225 }
5226 #endif
5227 return (ptr);
5228 }
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);
5248 }
5250 static void
5251 huge_dalloc(void *ptr)
5252 {
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);
5281 }
5283 #ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
5284 #ifdef MOZ_MEMORY_BSD
5285 static inline unsigned
5286 malloc_ncpus(void)
5287 {
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);
5298 }
5300 return (ret);
5301 }
5302 #elif (defined(MOZ_MEMORY_LINUX))
5303 #include <fcntl.h>
5305 static inline unsigned
5306 malloc_ncpus(void)
5307 {
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++;
5342 }
5343 } else
5344 column = -1;
5345 }
5346 }
5347 }
5349 if (ret == 0)
5350 ret = 1; /* Something went wrong in the parser. */
5351 close(fd);
5353 return (ret);
5354 }
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)
5361 {
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);
5373 }
5374 #elif (defined(MOZ_MEMORY_SOLARIS))
5376 static inline unsigned
5377 malloc_ncpus(void)
5378 {
5379 return sysconf(_SC_NPROCESSORS_ONLN);
5380 }
5381 #else
5382 static inline unsigned
5383 malloc_ncpus(void)
5384 {
5386 /*
5387 * We lack a way to determine the number of CPUs on this platform, so
5388 * assume 1 CPU.
5389 */
5390 return (1);
5391 }
5392 #endif
5393 #endif
5395 static void
5396 malloc_print_stats(void)
5397 {
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
5458 {
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);
5481 }
5482 }
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);
5526 }
5527 }
5528 }
5529 #endif /* #ifdef MALLOC_STATS */
5530 _malloc_message("--- End malloc statistics ---\n", "", "", "");
5531 }
5532 }
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)
5544 {
5546 if (malloc_initialized == false)
5547 return (malloc_init_hard());
5549 return (false);
5550 }
5551 #endif
5553 #if !defined(MOZ_MEMORY_WINDOWS)
5554 static
5555 #endif
5556 bool
5557 malloc_init_hard(void)
5558 {
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);
5583 }
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
5592 {
5593 SYSTEM_INFO info;
5595 GetSystemInfo(&info);
5596 result = info.dwPageSize;
5598 #ifndef MOZ_MEMORY_NARENAS_DEFAULT_ONE
5599 ncpus = info.dwNumberOfProcessors;
5600 #endif
5601 }
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();
5619 }
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:
5632 *
5633 * 1) MALLOC_TMPDIR
5634 * 2) TMPDIR
5635 * 3) P_tmpdir
5636 */
5637 {
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();
5651 }
5652 memcpy(pagefile_templ, s, slen);
5653 memcpy(&pagefile_templ[slen], suffix, sizeof(suffix));
5654 }
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
5674 {
5675 /* No configuration specified. */
5676 buf[0] = '\0';
5677 opts = buf;
5678 }
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;
5692 }
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;
5705 }
5706 break;
5707 default:
5708 /* NOTREACHED */
5709 buf[0] = '\0';
5710 opts = buf;
5711 assert(false);
5712 }
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;
5729 }
5730 }
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");
5888 }
5889 }
5890 }
5891 }
5892 }
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
5900 }
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;
5983 }
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;
6003 }
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;
6032 }
6033 }
6034 narenas = parenas;
6035 }
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);
6051 }
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);
6068 }
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");
6103 }
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.
6117 *
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
6132 }
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);
6142 }
6143 else {
6144 szone = default_zone;
6145 }
6146 #endif
6148 #ifndef MOZ_MEMORY_WINDOWS
6149 malloc_mutex_unlock(&init_lock);
6150 #endif
6151 return (false);
6152 }
6154 /* XXX Why not just expose malloc_print_stats()? */
6155 #ifdef MOZ_MEMORY_WINDOWS
6156 void
6157 malloc_shutdown()
6158 {
6160 malloc_print_stats();
6161 }
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.
6178 *
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.
6182 *
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)
6193 {
6194 void *ret;
6196 DARWIN_ONLY(return (szone->malloc)(szone, size));
6198 if (malloc_init()) {
6199 ret = NULL;
6200 goto RETURN;
6201 }
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;
6212 }
6213 #endif
6214 }
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();
6226 }
6227 #endif
6228 errno = ENOMEM;
6229 }
6231 UTRACE(0, size, ret);
6232 return (ret);
6233 }
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.
6241 *
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)
6277 {
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;
6287 }
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;
6298 }
6299 #endif
6300 }
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();
6311 }
6312 #endif
6313 UTRACE(0, size, ret);
6314 return (ret);
6315 }
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)
6324 {
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();
6335 }
6336 #endif
6337 return (EINVAL);
6338 }
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);
6349 }
6351 MOZ_MEMORY_API void *
6352 aligned_alloc_impl(size_t alignment, size_t size)
6353 {
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();
6361 }
6362 #endif
6363 return (NULL);
6364 }
6365 return MEMALIGN(alignment, size);
6366 }
6368 MOZ_MEMORY_API void *
6369 valloc_impl(size_t size)
6370 {
6371 return (MEMALIGN(pagesize, size));
6372 }
6374 MOZ_MEMORY_API void *
6375 calloc_impl(size_t num, size_t size)
6376 {
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;
6386 }
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;
6398 }
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;
6410 }
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();
6422 }
6423 #endif
6424 errno = ENOMEM;
6425 }
6427 UTRACE(0, num_size, ret);
6428 return (ret);
6429 }
6431 MOZ_MEMORY_API void *
6432 realloc_impl(void *ptr, size_t size)
6433 {
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;
6449 }
6450 #endif
6451 }
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();
6465 }
6466 #endif
6467 errno = ENOMEM;
6468 }
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();
6482 }
6483 #endif
6484 errno = ENOMEM;
6485 }
6486 }
6488 #ifdef MALLOC_SYSV
6489 RETURN:
6490 #endif
6491 UTRACE(ptr, size, ret);
6492 return (ret);
6493 }
6495 MOZ_MEMORY_API void
6496 free_impl(void *ptr)
6497 {
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);
6514 }
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)
6532 {
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);
6564 }
6565 return size;
6566 }
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
6576 {
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
6586 }
6588 MOZ_JEMALLOC_API void
6589 jemalloc_stats_impl(jemalloc_stats_t *stats)
6590 {
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
6636 ;
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;
6673 }
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;
6698 }
6700 assert(stats->mapped >= stats->allocated + stats->waste +
6701 stats->page_cache + stats->bookkeeping);
6702 }
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)
6709 {
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;
6723 }
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);
6730 }
6731 i += npages;
6732 }
6733 }
6735 /* Explicitly remove all of this arena's MADV_FREE'd pages from memory. */
6736 static void
6737 hard_purge_arena(arena_t *arena)
6738 {
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);
6748 }
6750 malloc_spin_unlock(&arena->lock);
6751 }
6753 MOZ_JEMALLOC_API void
6754 jemalloc_purge_freed_pages_impl()
6755 {
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);
6761 }
6762 }
6764 #else /* !defined MALLOC_DOUBLE_PURGE */
6766 MOZ_JEMALLOC_API void
6767 jemalloc_purge_freed_pages_impl()
6768 {
6769 /* Do nothing. */
6770 }
6772 #endif /* defined MALLOC_DOUBLE_PURGE */
6776 #ifdef MOZ_MEMORY_WINDOWS
6777 void*
6778 _recalloc(void *ptr, size_t count, size_t size)
6779 {
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);
6795 }
6797 return ptr;
6798 }
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)
6806 {
6807 if (isalloc(ptr) >= newsize)
6808 return ptr;
6810 return NULL;
6811 }
6813 size_t
6814 _msize(const void *ptr)
6815 {
6817 return malloc_usable_size_impl(ptr);
6818 }
6819 #endif
6821 MOZ_JEMALLOC_API void
6822 jemalloc_free_dirty_pages_impl(void)
6823 {
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);
6832 }
6833 }
6834 }
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)
6849 {
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);
6858 }
6860 malloc_mutex_lock(&base_mtx);
6862 malloc_mutex_lock(&huge_mtx);
6863 }
6865 static void
6866 _malloc_postfork(void)
6867 {
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);
6879 }
6880 malloc_spin_unlock(&arenas_lock);
6881 }
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)
6897 {
6899 return (malloc_impl(size));
6900 }
6902 static void *
6903 zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
6904 {
6906 return (calloc_impl(num, size));
6907 }
6909 static void *
6910 zone_valloc(malloc_zone_t *zone, size_t size)
6911 {
6912 void *ret = NULL; /* Assignment avoids useless compiler warning. */
6914 posix_memalign_impl(&ret, pagesize, size);
6916 return (ret);
6917 }
6919 static void *
6920 zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
6921 {
6922 return (memalign_impl(alignment, size));
6923 }
6925 static void *
6926 zone_destroy(malloc_zone_t *zone)
6927 {
6929 /* This function should never be called. */
6930 assert(false);
6931 return (NULL);
6932 }
6934 static size_t
6935 zone_good_size(malloc_zone_t *zone, size_t size)
6936 {
6937 return malloc_good_size_impl(size);
6938 }
6940 static size_t
6941 ozone_size(malloc_zone_t *zone, void *ptr)
6942 {
6943 size_t ret = isalloc_validate(ptr);
6944 if (ret == 0)
6945 ret = szone->size(zone, ptr);
6947 return ret;
6948 }
6950 static void
6951 ozone_free(malloc_zone_t *zone, void *ptr)
6952 {
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. */
6960 }
6961 }
6963 static void *
6964 ozone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
6965 {
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);
6983 }
6984 return (ret);
6985 }
6986 }
6987 }
6989 static unsigned
6990 ozone_batch_malloc(malloc_zone_t *zone, size_t size, void **results,
6991 unsigned num_requested)
6992 {
6993 /* Don't bother implementing this interface, since it isn't required. */
6994 return 0;
6995 }
6997 static void
6998 ozone_batch_free(malloc_zone_t *zone, void **to_be_freed, unsigned num)
6999 {
7000 unsigned i;
7002 for (i = 0; i < num; i++)
7003 ozone_free(zone, to_be_freed[i]);
7004 }
7006 static void
7007 ozone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
7008 {
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);
7015 }
7016 }
7018 static void
7019 ozone_force_lock(malloc_zone_t *zone)
7020 {
7021 _malloc_prefork();
7022 szone->introspect->force_lock(zone);
7023 }
7025 static void
7026 ozone_force_unlock(malloc_zone_t *zone)
7027 {
7028 szone->introspect->force_unlock(zone);
7029 _malloc_postfork();
7030 }
7032 static size_t
7033 zone_version_size(int version)
7034 {
7035 switch (version)
7036 {
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);
7044 }
7045 }
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)
7055 {
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);
7072 }
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;
7104 }
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;
7112 }
7113 }
7114 #endif
7116 __attribute__((constructor))
7117 void
7118 jemalloc_darwin_init(void)
7119 {
7120 if (malloc_init_hard())
7121 abort();
7122 }
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).
7140 *
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)
7170 {
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;
7183 }
7185 return TRUE;
7186 }
7187 #endif