Home | History | Annotate | Download | only in internal
      1 #ifndef JEMALLOC_INTERNAL_H
      2 #define	JEMALLOC_INTERNAL_H
      3 
      4 #include "jemalloc_internal_defs.h"
      5 #include "jemalloc/internal/jemalloc_internal_decls.h"
      6 
      7 #ifdef JEMALLOC_UTRACE
      8 #include <sys/ktrace.h>
      9 #endif
     10 
     11 #define	JEMALLOC_NO_DEMANGLE
     12 #ifdef JEMALLOC_JET
     13 #  define JEMALLOC_N(n) jet_##n
     14 #  include "jemalloc/internal/public_namespace.h"
     15 #  define JEMALLOC_NO_RENAME
     16 #  include "../jemalloc.h"
     17 #  undef JEMALLOC_NO_RENAME
     18 #else
     19 #  define JEMALLOC_N(n) je_##n
     20 #  include "../jemalloc.h"
     21 #endif
     22 #include "jemalloc/internal/private_namespace.h"
     23 
     24 static const bool config_debug =
     25 #ifdef JEMALLOC_DEBUG
     26     true
     27 #else
     28     false
     29 #endif
     30     ;
     31 static const bool have_dss =
     32 #ifdef JEMALLOC_DSS
     33     true
     34 #else
     35     false
     36 #endif
     37     ;
     38 static const bool config_fill =
     39 #ifdef JEMALLOC_FILL
     40     true
     41 #else
     42     false
     43 #endif
     44     ;
     45 static const bool config_lazy_lock =
     46 #ifdef JEMALLOC_LAZY_LOCK
     47     true
     48 #else
     49     false
     50 #endif
     51     ;
     52 static const char * const config_malloc_conf = JEMALLOC_CONFIG_MALLOC_CONF;
     53 static const bool config_prof =
     54 #ifdef JEMALLOC_PROF
     55     true
     56 #else
     57     false
     58 #endif
     59     ;
     60 static const bool config_prof_libgcc =
     61 #ifdef JEMALLOC_PROF_LIBGCC
     62     true
     63 #else
     64     false
     65 #endif
     66     ;
     67 static const bool config_prof_libunwind =
     68 #ifdef JEMALLOC_PROF_LIBUNWIND
     69     true
     70 #else
     71     false
     72 #endif
     73     ;
     74 static const bool maps_coalesce =
     75 #ifdef JEMALLOC_MAPS_COALESCE
     76     true
     77 #else
     78     false
     79 #endif
     80     ;
     81 static const bool config_munmap =
     82 #ifdef JEMALLOC_MUNMAP
     83     true
     84 #else
     85     false
     86 #endif
     87     ;
     88 static const bool config_stats =
     89 #ifdef JEMALLOC_STATS
     90     true
     91 #else
     92     false
     93 #endif
     94     ;
     95 static const bool config_tcache =
     96 #ifdef JEMALLOC_TCACHE
     97     true
     98 #else
     99     false
    100 #endif
    101     ;
    102 static const bool config_tls =
    103 #ifdef JEMALLOC_TLS
    104     true
    105 #else
    106     false
    107 #endif
    108     ;
    109 static const bool config_utrace =
    110 #ifdef JEMALLOC_UTRACE
    111     true
    112 #else
    113     false
    114 #endif
    115     ;
    116 static const bool config_valgrind =
    117 #ifdef JEMALLOC_VALGRIND
    118     true
    119 #else
    120     false
    121 #endif
    122     ;
    123 static const bool config_xmalloc =
    124 #ifdef JEMALLOC_XMALLOC
    125     true
    126 #else
    127     false
    128 #endif
    129     ;
    130 static const bool config_ivsalloc =
    131 #ifdef JEMALLOC_IVSALLOC
    132     true
    133 #else
    134     false
    135 #endif
    136     ;
    137 static const bool config_cache_oblivious =
    138 #ifdef JEMALLOC_CACHE_OBLIVIOUS
    139     true
    140 #else
    141     false
    142 #endif
    143     ;
    144 
    145 #ifdef JEMALLOC_C11ATOMICS
    146 #include <stdatomic.h>
    147 #endif
    148 
    149 #ifdef JEMALLOC_ATOMIC9
    150 #include <machine/atomic.h>
    151 #endif
    152 
    153 #if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))
    154 #include <libkern/OSAtomic.h>
    155 #endif
    156 
    157 #ifdef JEMALLOC_ZONE
    158 #include <mach/mach_error.h>
    159 #include <mach/mach_init.h>
    160 #include <mach/vm_map.h>
    161 #include <malloc/malloc.h>
    162 #endif
    163 
    164 #include "jemalloc/internal/ph.h"
    165 #ifndef __PGI
    166 #define	RB_COMPACT
    167 #endif
    168 #include "jemalloc/internal/rb.h"
    169 #include "jemalloc/internal/qr.h"
    170 #include "jemalloc/internal/ql.h"
    171 
    172 /*
    173  * jemalloc can conceptually be broken into components (arena, tcache, etc.),
    174  * but there are circular dependencies that cannot be broken without
    175  * substantial performance degradation.  In order to reduce the effect on
    176  * visual code flow, read the header files in multiple passes, with one of the
    177  * following cpp variables defined during each pass:
    178  *
    179  *   JEMALLOC_H_TYPES   : Preprocessor-defined constants and psuedo-opaque data
    180  *                        types.
    181  *   JEMALLOC_H_STRUCTS : Data structures.
    182  *   JEMALLOC_H_EXTERNS : Extern data declarations and function prototypes.
    183  *   JEMALLOC_H_INLINES : Inline functions.
    184  */
    185 /******************************************************************************/
    186 #define	JEMALLOC_H_TYPES
    187 
    188 #include "jemalloc/internal/jemalloc_internal_macros.h"
    189 
    190 /* Page size index type. */
    191 typedef unsigned pszind_t;
    192 
    193 /* Size class index type. */
    194 typedef unsigned szind_t;
    195 
    196 /*
    197  * Flags bits:
    198  *
    199  * a: arena
    200  * t: tcache
    201  * 0: unused
    202  * z: zero
    203  * n: alignment
    204  *
    205  * aaaaaaaa aaaatttt tttttttt 0znnnnnn
    206  */
    207 #define	MALLOCX_ARENA_MASK	((int)~0xfffff)
    208 #define	MALLOCX_ARENA_MAX	0xffe
    209 #define	MALLOCX_TCACHE_MASK	((int)~0xfff000ffU)
    210 #define	MALLOCX_TCACHE_MAX	0xffd
    211 #define	MALLOCX_LG_ALIGN_MASK	((int)0x3f)
    212 /* Use MALLOCX_ALIGN_GET() if alignment may not be specified in flags. */
    213 #define	MALLOCX_ALIGN_GET_SPECIFIED(flags)				\
    214     (ZU(1) << (flags & MALLOCX_LG_ALIGN_MASK))
    215 #define	MALLOCX_ALIGN_GET(flags)					\
    216     (MALLOCX_ALIGN_GET_SPECIFIED(flags) & (SIZE_T_MAX-1))
    217 #define	MALLOCX_ZERO_GET(flags)						\
    218     ((bool)(flags & MALLOCX_ZERO))
    219 
    220 #define	MALLOCX_TCACHE_GET(flags)					\
    221     (((unsigned)((flags & MALLOCX_TCACHE_MASK) >> 8)) - 2)
    222 #define	MALLOCX_ARENA_GET(flags)					\
    223     (((unsigned)(((unsigned)flags) >> 20)) - 1)
    224 
    225 /* Smallest size class to support. */
    226 #define	TINY_MIN		(1U << LG_TINY_MIN)
    227 
    228 /*
    229  * Minimum allocation alignment is 2^LG_QUANTUM bytes (ignoring tiny size
    230  * classes).
    231  */
    232 #ifndef LG_QUANTUM
    233 #  if (defined(__i386__) || defined(_M_IX86))
    234 #    define LG_QUANTUM		4
    235 #  endif
    236 #  ifdef __ia64__
    237 #    define LG_QUANTUM		4
    238 #  endif
    239 #  ifdef __alpha__
    240 #    define LG_QUANTUM		4
    241 #  endif
    242 #  if (defined(__sparc64__) || defined(__sparcv9) || defined(__sparc_v9__))
    243 #    define LG_QUANTUM		4
    244 #  endif
    245 #  if (defined(__amd64__) || defined(__x86_64__) || defined(_M_X64))
    246 #    define LG_QUANTUM		4
    247 #  endif
    248 #  ifdef __arm__
    249 #    define LG_QUANTUM		3
    250 #  endif
    251 #  ifdef __aarch64__
    252 #    define LG_QUANTUM		4
    253 #  endif
    254 #  ifdef __hppa__
    255 #    define LG_QUANTUM		4
    256 #  endif
    257 #  ifdef __mips__
    258 #    define LG_QUANTUM		3
    259 #  endif
    260 #  ifdef __or1k__
    261 #    define LG_QUANTUM		3
    262 #  endif
    263 #  ifdef __powerpc__
    264 #    define LG_QUANTUM		4
    265 #  endif
    266 #  ifdef __riscv__
    267 #    define LG_QUANTUM		4
    268 #  endif
    269 #  ifdef __s390__
    270 #    define LG_QUANTUM		4
    271 #  endif
    272 #  ifdef __SH4__
    273 #    define LG_QUANTUM		4
    274 #  endif
    275 #  ifdef __tile__
    276 #    define LG_QUANTUM		4
    277 #  endif
    278 #  ifdef __le32__
    279 #    define LG_QUANTUM		4
    280 #  endif
    281 #  ifndef LG_QUANTUM
    282 #    error "Unknown minimum alignment for architecture; specify via "
    283 	 "--with-lg-quantum"
    284 #  endif
    285 #endif
    286 
    287 #define	QUANTUM			((size_t)(1U << LG_QUANTUM))
    288 #define	QUANTUM_MASK		(QUANTUM - 1)
    289 
    290 /* Return the smallest quantum multiple that is >= a. */
    291 #define	QUANTUM_CEILING(a)						\
    292 	(((a) + QUANTUM_MASK) & ~QUANTUM_MASK)
    293 
    294 #define	LONG			((size_t)(1U << LG_SIZEOF_LONG))
    295 #define	LONG_MASK		(LONG - 1)
    296 
    297 /* Return the smallest long multiple that is >= a. */
    298 #define	LONG_CEILING(a)							\
    299 	(((a) + LONG_MASK) & ~LONG_MASK)
    300 
    301 #define	SIZEOF_PTR		(1U << LG_SIZEOF_PTR)
    302 #define	PTR_MASK		(SIZEOF_PTR - 1)
    303 
    304 /* Return the smallest (void *) multiple that is >= a. */
    305 #define	PTR_CEILING(a)							\
    306 	(((a) + PTR_MASK) & ~PTR_MASK)
    307 
    308 /*
    309  * Maximum size of L1 cache line.  This is used to avoid cache line aliasing.
    310  * In addition, this controls the spacing of cacheline-spaced size classes.
    311  *
    312  * CACHELINE cannot be based on LG_CACHELINE because __declspec(align()) can
    313  * only handle raw constants.
    314  */
    315 #define	LG_CACHELINE		6
    316 #define	CACHELINE		64
    317 #define	CACHELINE_MASK		(CACHELINE - 1)
    318 
    319 /* Return the smallest cacheline multiple that is >= s. */
    320 #define	CACHELINE_CEILING(s)						\
    321 	(((s) + CACHELINE_MASK) & ~CACHELINE_MASK)
    322 
    323 /* Page size.  LG_PAGE is determined by the configure script. */
    324 #ifdef PAGE_MASK
    325 #  undef PAGE_MASK
    326 #endif
    327 #define	PAGE		((size_t)(1U << LG_PAGE))
    328 #define	PAGE_MASK	((size_t)(PAGE - 1))
    329 
    330 /* Return the page base address for the page containing address a. */
    331 #define	PAGE_ADDR2BASE(a)						\
    332 	((void *)((uintptr_t)(a) & ~PAGE_MASK))
    333 
    334 /* Return the smallest pagesize multiple that is >= s. */
    335 #define	PAGE_CEILING(s)							\
    336 	(((s) + PAGE_MASK) & ~PAGE_MASK)
    337 
    338 /* Return the nearest aligned address at or below a. */
    339 #define	ALIGNMENT_ADDR2BASE(a, alignment)				\
    340 	((void *)((uintptr_t)(a) & ((~(alignment)) + 1)))
    341 
    342 /* Return the offset between a and the nearest aligned address at or below a. */
    343 #define	ALIGNMENT_ADDR2OFFSET(a, alignment)				\
    344 	((size_t)((uintptr_t)(a) & (alignment - 1)))
    345 
    346 /* Return the smallest alignment multiple that is >= s. */
    347 #define	ALIGNMENT_CEILING(s, alignment)					\
    348 	(((s) + (alignment - 1)) & ((~(alignment)) + 1))
    349 
    350 /* Declare a variable-length array. */
    351 #if __STDC_VERSION__ < 199901L
    352 #  ifdef _MSC_VER
    353 #    include <malloc.h>
    354 #    define alloca _alloca
    355 #  else
    356 #    ifdef JEMALLOC_HAS_ALLOCA_H
    357 #      include <alloca.h>
    358 #    else
    359 #      include <stdlib.h>
    360 #    endif
    361 #  endif
    362 #  define VARIABLE_ARRAY(type, name, count) \
    363 	type *name = alloca(sizeof(type) * (count))
    364 #else
    365 #  define VARIABLE_ARRAY(type, name, count) type name[(count)]
    366 #endif
    367 
    368 #include "jemalloc/internal/nstime.h"
    369 #include "jemalloc/internal/valgrind.h"
    370 #include "jemalloc/internal/util.h"
    371 #include "jemalloc/internal/atomic.h"
    372 #include "jemalloc/internal/spin.h"
    373 #include "jemalloc/internal/prng.h"
    374 #include "jemalloc/internal/ticker.h"
    375 #include "jemalloc/internal/ckh.h"
    376 #include "jemalloc/internal/size_classes.h"
    377 #include "jemalloc/internal/smoothstep.h"
    378 #include "jemalloc/internal/stats.h"
    379 #include "jemalloc/internal/ctl.h"
    380 #include "jemalloc/internal/witness.h"
    381 #include "jemalloc/internal/mutex.h"
    382 #include "jemalloc/internal/tsd.h"
    383 #include "jemalloc/internal/mb.h"
    384 #include "jemalloc/internal/extent.h"
    385 #include "jemalloc/internal/arena.h"
    386 #include "jemalloc/internal/bitmap.h"
    387 #include "jemalloc/internal/base.h"
    388 #include "jemalloc/internal/rtree.h"
    389 #include "jemalloc/internal/pages.h"
    390 #include "jemalloc/internal/chunk.h"
    391 #include "jemalloc/internal/huge.h"
    392 #include "jemalloc/internal/tcache.h"
    393 #include "jemalloc/internal/hash.h"
    394 #include "jemalloc/internal/quarantine.h"
    395 #include "jemalloc/internal/prof.h"
    396 
    397 #undef JEMALLOC_H_TYPES
    398 /******************************************************************************/
    399 #define	JEMALLOC_H_STRUCTS
    400 
    401 #include "jemalloc/internal/nstime.h"
    402 #include "jemalloc/internal/valgrind.h"
    403 #include "jemalloc/internal/util.h"
    404 #include "jemalloc/internal/atomic.h"
    405 #include "jemalloc/internal/spin.h"
    406 #include "jemalloc/internal/prng.h"
    407 #include "jemalloc/internal/ticker.h"
    408 #include "jemalloc/internal/ckh.h"
    409 #include "jemalloc/internal/size_classes.h"
    410 #include "jemalloc/internal/smoothstep.h"
    411 #include "jemalloc/internal/stats.h"
    412 #include "jemalloc/internal/ctl.h"
    413 #include "jemalloc/internal/witness.h"
    414 #include "jemalloc/internal/mutex.h"
    415 #include "jemalloc/internal/mb.h"
    416 #include "jemalloc/internal/bitmap.h"
    417 #define	JEMALLOC_ARENA_STRUCTS_A
    418 #include "jemalloc/internal/arena.h"
    419 #undef JEMALLOC_ARENA_STRUCTS_A
    420 #include "jemalloc/internal/extent.h"
    421 #define	JEMALLOC_ARENA_STRUCTS_B
    422 #include "jemalloc/internal/arena.h"
    423 #undef JEMALLOC_ARENA_STRUCTS_B
    424 #include "jemalloc/internal/base.h"
    425 #include "jemalloc/internal/rtree.h"
    426 #include "jemalloc/internal/pages.h"
    427 #include "jemalloc/internal/chunk.h"
    428 #include "jemalloc/internal/huge.h"
    429 #include "jemalloc/internal/tcache.h"
    430 #include "jemalloc/internal/hash.h"
    431 #include "jemalloc/internal/quarantine.h"
    432 #include "jemalloc/internal/prof.h"
    433 
    434 #include "jemalloc/internal/tsd.h"
    435 
    436 #undef JEMALLOC_H_STRUCTS
    437 /******************************************************************************/
    438 #define	JEMALLOC_H_EXTERNS
    439 
    440 extern bool	opt_abort;
    441 extern const char	*opt_junk;
    442 extern bool	opt_junk_alloc;
    443 extern bool	opt_junk_free;
    444 extern size_t	opt_quarantine;
    445 extern bool	opt_redzone;
    446 extern bool	opt_utrace;
    447 extern bool	opt_xmalloc;
    448 extern bool	opt_zero;
    449 extern unsigned	opt_narenas;
    450 
    451 extern bool	in_valgrind;
    452 
    453 /* Number of CPUs. */
    454 extern unsigned	ncpus;
    455 
    456 /* Number of arenas used for automatic multiplexing of threads and arenas. */
    457 extern unsigned	narenas_auto;
    458 
    459 /*
    460  * Arenas that are used to service external requests.  Not all elements of the
    461  * arenas array are necessarily used; arenas are created lazily as needed.
    462  */
    463 extern arena_t	**arenas;
    464 
    465 /*
    466  * pind2sz_tab encodes the same information as could be computed by
    467  * pind2sz_compute().
    468  */
    469 extern size_t const	pind2sz_tab[NPSIZES];
    470 /*
    471  * index2size_tab encodes the same information as could be computed (at
    472  * unacceptable cost in some code paths) by index2size_compute().
    473  */
    474 extern size_t const	index2size_tab[NSIZES];
    475 /*
    476  * size2index_tab is a compact lookup table that rounds request sizes up to
    477  * size classes.  In order to reduce cache footprint, the table is compressed,
    478  * and all accesses are via size2index().
    479  */
    480 extern uint8_t const	size2index_tab[];
    481 
    482 arena_t	*a0get(void);
    483 void	*a0malloc(size_t size);
    484 void	a0dalloc(void *ptr);
    485 void	*bootstrap_malloc(size_t size);
    486 void	*bootstrap_calloc(size_t num, size_t size);
    487 void	bootstrap_free(void *ptr);
    488 unsigned	narenas_total_get(void);
    489 arena_t	*arena_init(tsdn_t *tsdn, unsigned ind);
    490 arena_tdata_t	*arena_tdata_get_hard(tsd_t *tsd, unsigned ind);
    491 arena_t	*arena_choose_hard(tsd_t *tsd, bool internal);
    492 void	arena_migrate(tsd_t *tsd, unsigned oldind, unsigned newind);
    493 void	thread_allocated_cleanup(tsd_t *tsd);
    494 void	thread_deallocated_cleanup(tsd_t *tsd);
    495 void	iarena_cleanup(tsd_t *tsd);
    496 void	arena_cleanup(tsd_t *tsd);
    497 void	arenas_tdata_cleanup(tsd_t *tsd);
    498 void	narenas_tdata_cleanup(tsd_t *tsd);
    499 void	arenas_tdata_bypass_cleanup(tsd_t *tsd);
    500 void	jemalloc_prefork(void);
    501 void	jemalloc_postfork_parent(void);
    502 void	jemalloc_postfork_child(void);
    503 
    504 #include "jemalloc/internal/nstime.h"
    505 #include "jemalloc/internal/valgrind.h"
    506 #include "jemalloc/internal/util.h"
    507 #include "jemalloc/internal/atomic.h"
    508 #include "jemalloc/internal/spin.h"
    509 #include "jemalloc/internal/prng.h"
    510 #include "jemalloc/internal/ticker.h"
    511 #include "jemalloc/internal/ckh.h"
    512 #include "jemalloc/internal/size_classes.h"
    513 #include "jemalloc/internal/smoothstep.h"
    514 #include "jemalloc/internal/stats.h"
    515 #include "jemalloc/internal/ctl.h"
    516 #include "jemalloc/internal/witness.h"
    517 #include "jemalloc/internal/mutex.h"
    518 #include "jemalloc/internal/mb.h"
    519 #include "jemalloc/internal/bitmap.h"
    520 #include "jemalloc/internal/extent.h"
    521 #include "jemalloc/internal/arena.h"
    522 #include "jemalloc/internal/base.h"
    523 #include "jemalloc/internal/rtree.h"
    524 #include "jemalloc/internal/pages.h"
    525 #include "jemalloc/internal/chunk.h"
    526 #include "jemalloc/internal/huge.h"
    527 #include "jemalloc/internal/tcache.h"
    528 #include "jemalloc/internal/hash.h"
    529 #include "jemalloc/internal/quarantine.h"
    530 #include "jemalloc/internal/prof.h"
    531 #include "jemalloc/internal/tsd.h"
    532 
    533 #undef JEMALLOC_H_EXTERNS
    534 /******************************************************************************/
    535 #define	JEMALLOC_H_INLINES
    536 
    537 #include "jemalloc/internal/nstime.h"
    538 #include "jemalloc/internal/valgrind.h"
    539 #include "jemalloc/internal/util.h"
    540 #include "jemalloc/internal/atomic.h"
    541 #include "jemalloc/internal/spin.h"
    542 #include "jemalloc/internal/prng.h"
    543 #include "jemalloc/internal/ticker.h"
    544 #include "jemalloc/internal/ckh.h"
    545 #include "jemalloc/internal/size_classes.h"
    546 #include "jemalloc/internal/smoothstep.h"
    547 #include "jemalloc/internal/stats.h"
    548 #include "jemalloc/internal/ctl.h"
    549 #include "jemalloc/internal/tsd.h"
    550 #include "jemalloc/internal/witness.h"
    551 #include "jemalloc/internal/mutex.h"
    552 #include "jemalloc/internal/mb.h"
    553 #include "jemalloc/internal/extent.h"
    554 #include "jemalloc/internal/base.h"
    555 #include "jemalloc/internal/rtree.h"
    556 #include "jemalloc/internal/pages.h"
    557 #include "jemalloc/internal/chunk.h"
    558 #include "jemalloc/internal/huge.h"
    559 
    560 #ifndef JEMALLOC_ENABLE_INLINE
    561 pszind_t	psz2ind(size_t psz);
    562 size_t	pind2sz_compute(pszind_t pind);
    563 size_t	pind2sz_lookup(pszind_t pind);
    564 size_t	pind2sz(pszind_t pind);
    565 size_t	psz2u(size_t psz);
    566 szind_t	size2index_compute(size_t size);
    567 szind_t	size2index_lookup(size_t size);
    568 szind_t	size2index(size_t size);
    569 size_t	index2size_compute(szind_t index);
    570 size_t	index2size_lookup(szind_t index);
    571 size_t	index2size(szind_t index);
    572 size_t	s2u_compute(size_t size);
    573 size_t	s2u_lookup(size_t size);
    574 size_t	s2u(size_t size);
    575 size_t	sa2u(size_t size, size_t alignment);
    576 arena_t	*arena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal);
    577 arena_t	*arena_choose(tsd_t *tsd, arena_t *arena);
    578 arena_t	*arena_ichoose(tsd_t *tsd, arena_t *arena);
    579 arena_tdata_t	*arena_tdata_get(tsd_t *tsd, unsigned ind,
    580     bool refresh_if_missing);
    581 arena_t	*arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing);
    582 ticker_t	*decay_ticker_get(tsd_t *tsd, unsigned ind);
    583 #endif
    584 
    585 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
    586 JEMALLOC_INLINE pszind_t
    587 psz2ind(size_t psz)
    588 {
    589 
    590 	if (unlikely(psz > HUGE_MAXCLASS))
    591 		return (NPSIZES);
    592 	{
    593 		pszind_t x = lg_floor((psz<<1)-1);
    594 		pszind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_PAGE) ? 0 : x -
    595 		    (LG_SIZE_CLASS_GROUP + LG_PAGE);
    596 		pszind_t grp = shift << LG_SIZE_CLASS_GROUP;
    597 
    598 		pszind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
    599 		    LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
    600 
    601 		size_t delta_inverse_mask = ZI(-1) << lg_delta;
    602 		pszind_t mod = ((((psz-1) & delta_inverse_mask) >> lg_delta)) &
    603 		    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
    604 
    605 		pszind_t ind = grp + mod;
    606 		return (ind);
    607 	}
    608 }
    609 
    610 JEMALLOC_INLINE size_t
    611 pind2sz_compute(pszind_t pind)
    612 {
    613 
    614 	{
    615 		size_t grp = pind >> LG_SIZE_CLASS_GROUP;
    616 		size_t mod = pind & ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
    617 
    618 		size_t grp_size_mask = ~((!!grp)-1);
    619 		size_t grp_size = ((ZU(1) << (LG_PAGE +
    620 		    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;
    621 
    622 		size_t shift = (grp == 0) ? 1 : grp;
    623 		size_t lg_delta = shift + (LG_PAGE-1);
    624 		size_t mod_size = (mod+1) << lg_delta;
    625 
    626 		size_t sz = grp_size + mod_size;
    627 		return (sz);
    628 	}
    629 }
    630 
    631 JEMALLOC_INLINE size_t
    632 pind2sz_lookup(pszind_t pind)
    633 {
    634 	size_t ret = (size_t)pind2sz_tab[pind];
    635 	assert(ret == pind2sz_compute(pind));
    636 	return (ret);
    637 }
    638 
    639 JEMALLOC_INLINE size_t
    640 pind2sz(pszind_t pind)
    641 {
    642 
    643 	assert(pind < NPSIZES);
    644 	return (pind2sz_lookup(pind));
    645 }
    646 
    647 JEMALLOC_INLINE size_t
    648 psz2u(size_t psz)
    649 {
    650 
    651 	if (unlikely(psz > HUGE_MAXCLASS))
    652 		return (0);
    653 	{
    654 		size_t x = lg_floor((psz<<1)-1);
    655 		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
    656 		    LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
    657 		size_t delta = ZU(1) << lg_delta;
    658 		size_t delta_mask = delta - 1;
    659 		size_t usize = (psz + delta_mask) & ~delta_mask;
    660 		return (usize);
    661 	}
    662 }
    663 
    664 JEMALLOC_INLINE szind_t
    665 size2index_compute(size_t size)
    666 {
    667 
    668 	if (unlikely(size > HUGE_MAXCLASS))
    669 		return (NSIZES);
    670 #if (NTBINS != 0)
    671 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
    672 		szind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
    673 		szind_t lg_ceil = lg_floor(pow2_ceil_zu(size));
    674 		return (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin);
    675 	}
    676 #endif
    677 	{
    678 		szind_t x = lg_floor((size<<1)-1);
    679 		szind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :
    680 		    x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);
    681 		szind_t grp = shift << LG_SIZE_CLASS_GROUP;
    682 
    683 		szind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
    684 		    ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
    685 
    686 		size_t delta_inverse_mask = ZI(-1) << lg_delta;
    687 		szind_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) &
    688 		    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
    689 
    690 		szind_t index = NTBINS + grp + mod;
    691 		return (index);
    692 	}
    693 }
    694 
    695 JEMALLOC_ALWAYS_INLINE szind_t
    696 size2index_lookup(size_t size)
    697 {
    698 
    699 	assert(size <= LOOKUP_MAXCLASS);
    700 	{
    701 		szind_t ret = (size2index_tab[(size-1) >> LG_TINY_MIN]);
    702 		assert(ret == size2index_compute(size));
    703 		return (ret);
    704 	}
    705 }
    706 
    707 JEMALLOC_ALWAYS_INLINE szind_t
    708 size2index(size_t size)
    709 {
    710 
    711 	assert(size > 0);
    712 	if (likely(size <= LOOKUP_MAXCLASS))
    713 		return (size2index_lookup(size));
    714 	return (size2index_compute(size));
    715 }
    716 
    717 JEMALLOC_INLINE size_t
    718 index2size_compute(szind_t index)
    719 {
    720 
    721 #if (NTBINS > 0)
    722 	if (index < NTBINS)
    723 		return (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index));
    724 #endif
    725 	{
    726 		size_t reduced_index = index - NTBINS;
    727 		size_t grp = reduced_index >> LG_SIZE_CLASS_GROUP;
    728 		size_t mod = reduced_index & ((ZU(1) << LG_SIZE_CLASS_GROUP) -
    729 		    1);
    730 
    731 		size_t grp_size_mask = ~((!!grp)-1);
    732 		size_t grp_size = ((ZU(1) << (LG_QUANTUM +
    733 		    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;
    734 
    735 		size_t shift = (grp == 0) ? 1 : grp;
    736 		size_t lg_delta = shift + (LG_QUANTUM-1);
    737 		size_t mod_size = (mod+1) << lg_delta;
    738 
    739 		size_t usize = grp_size + mod_size;
    740 		return (usize);
    741 	}
    742 }
    743 
    744 JEMALLOC_ALWAYS_INLINE size_t
    745 index2size_lookup(szind_t index)
    746 {
    747 	size_t ret = (size_t)index2size_tab[index];
    748 	assert(ret == index2size_compute(index));
    749 	return (ret);
    750 }
    751 
    752 JEMALLOC_ALWAYS_INLINE size_t
    753 index2size(szind_t index)
    754 {
    755 
    756 	assert(index < NSIZES);
    757 	return (index2size_lookup(index));
    758 }
    759 
    760 JEMALLOC_ALWAYS_INLINE size_t
    761 s2u_compute(size_t size)
    762 {
    763 
    764 	if (unlikely(size > HUGE_MAXCLASS))
    765 		return (0);
    766 #if (NTBINS > 0)
    767 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
    768 		size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
    769 		size_t lg_ceil = lg_floor(pow2_ceil_zu(size));
    770 		return (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) :
    771 		    (ZU(1) << lg_ceil));
    772 	}
    773 #endif
    774 	{
    775 		size_t x = lg_floor((size<<1)-1);
    776 		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
    777 		    ?  LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
    778 		size_t delta = ZU(1) << lg_delta;
    779 		size_t delta_mask = delta - 1;
    780 		size_t usize = (size + delta_mask) & ~delta_mask;
    781 		return (usize);
    782 	}
    783 }
    784 
    785 JEMALLOC_ALWAYS_INLINE size_t
    786 s2u_lookup(size_t size)
    787 {
    788 	size_t ret = index2size_lookup(size2index_lookup(size));
    789 
    790 	assert(ret == s2u_compute(size));
    791 	return (ret);
    792 }
    793 
    794 /*
    795  * Compute usable size that would result from allocating an object with the
    796  * specified size.
    797  */
    798 JEMALLOC_ALWAYS_INLINE size_t
    799 s2u(size_t size)
    800 {
    801 
    802 	assert(size > 0);
    803 	if (likely(size <= LOOKUP_MAXCLASS))
    804 		return (s2u_lookup(size));
    805 	return (s2u_compute(size));
    806 }
    807 
    808 /*
    809  * Compute usable size that would result from allocating an object with the
    810  * specified size and alignment.
    811  */
    812 JEMALLOC_ALWAYS_INLINE size_t
    813 sa2u(size_t size, size_t alignment)
    814 {
    815 	size_t usize;
    816 
    817 	assert(alignment != 0 && ((alignment - 1) & alignment) == 0);
    818 
    819 	/* Try for a small size class. */
    820 	if (size <= SMALL_MAXCLASS && alignment < PAGE) {
    821 		/*
    822 		 * Round size up to the nearest multiple of alignment.
    823 		 *
    824 		 * This done, we can take advantage of the fact that for each
    825 		 * small size class, every object is aligned at the smallest
    826 		 * power of two that is non-zero in the base two representation
    827 		 * of the size.  For example:
    828 		 *
    829 		 *   Size |   Base 2 | Minimum alignment
    830 		 *   -----+----------+------------------
    831 		 *     96 |  1100000 |  32
    832 		 *    144 | 10100000 |  32
    833 		 *    192 | 11000000 |  64
    834 		 */
    835 		usize = s2u(ALIGNMENT_CEILING(size, alignment));
    836 		if (usize < LARGE_MINCLASS)
    837 			return (usize);
    838 	}
    839 
    840 	/* Try for a large size class. */
    841 	if (likely(size <= large_maxclass) && likely(alignment < chunksize)) {
    842 		/*
    843 		 * We can't achieve subpage alignment, so round up alignment
    844 		 * to the minimum that can actually be supported.
    845 		 */
    846 		alignment = PAGE_CEILING(alignment);
    847 
    848 		/* Make sure result is a large size class. */
    849 		usize = (size <= LARGE_MINCLASS) ? LARGE_MINCLASS : s2u(size);
    850 
    851 		/*
    852 		 * Calculate the size of the over-size run that arena_palloc()
    853 		 * would need to allocate in order to guarantee the alignment.
    854 		 */
    855 		if (usize + large_pad + alignment - PAGE <= arena_maxrun)
    856 			return (usize);
    857 	}
    858 
    859 	/* Huge size class.  Beware of overflow. */
    860 
    861 	if (unlikely(alignment > HUGE_MAXCLASS))
    862 		return (0);
    863 
    864 	/*
    865 	 * We can't achieve subchunk alignment, so round up alignment to the
    866 	 * minimum that can actually be supported.
    867 	 */
    868 	alignment = CHUNK_CEILING(alignment);
    869 
    870 	/* Make sure result is a huge size class. */
    871 	if (size <= chunksize)
    872 		usize = chunksize;
    873 	else {
    874 		usize = s2u(size);
    875 		if (usize < size) {
    876 			/* size_t overflow. */
    877 			return (0);
    878 		}
    879 	}
    880 
    881 	/*
    882 	 * Calculate the multi-chunk mapping that huge_palloc() would need in
    883 	 * order to guarantee the alignment.
    884 	 */
    885 	if (usize + alignment - PAGE < usize) {
    886 		/* size_t overflow. */
    887 		return (0);
    888 	}
    889 	return (usize);
    890 }
    891 
    892 /* Choose an arena based on a per-thread value. */
    893 JEMALLOC_INLINE arena_t *
    894 arena_choose_impl(tsd_t *tsd, arena_t *arena, bool internal)
    895 {
    896 	arena_t *ret;
    897 
    898 	if (arena != NULL)
    899 		return (arena);
    900 
    901 	ret = internal ? tsd_iarena_get(tsd) : tsd_arena_get(tsd);
    902 	if (unlikely(ret == NULL))
    903 		ret = arena_choose_hard(tsd, internal);
    904 
    905 	return (ret);
    906 }
    907 
    908 JEMALLOC_INLINE arena_t *
    909 arena_choose(tsd_t *tsd, arena_t *arena)
    910 {
    911 
    912 	return (arena_choose_impl(tsd, arena, false));
    913 }
    914 
    915 JEMALLOC_INLINE arena_t *
    916 arena_ichoose(tsd_t *tsd, arena_t *arena)
    917 {
    918 
    919 	return (arena_choose_impl(tsd, arena, true));
    920 }
    921 
    922 JEMALLOC_INLINE arena_tdata_t *
    923 arena_tdata_get(tsd_t *tsd, unsigned ind, bool refresh_if_missing)
    924 {
    925 	arena_tdata_t *tdata;
    926 	arena_tdata_t *arenas_tdata = tsd_arenas_tdata_get(tsd);
    927 
    928 	if (unlikely(arenas_tdata == NULL)) {
    929 		/* arenas_tdata hasn't been initialized yet. */
    930 		return (arena_tdata_get_hard(tsd, ind));
    931 	}
    932 	if (unlikely(ind >= tsd_narenas_tdata_get(tsd))) {
    933 		/*
    934 		 * ind is invalid, cache is old (too small), or tdata to be
    935 		 * initialized.
    936 		 */
    937 		return (refresh_if_missing ? arena_tdata_get_hard(tsd, ind) :
    938 		    NULL);
    939 	}
    940 
    941 	tdata = &arenas_tdata[ind];
    942 	if (likely(tdata != NULL) || !refresh_if_missing)
    943 		return (tdata);
    944 	return (arena_tdata_get_hard(tsd, ind));
    945 }
    946 
    947 JEMALLOC_INLINE arena_t *
    948 arena_get(tsdn_t *tsdn, unsigned ind, bool init_if_missing)
    949 {
    950 	arena_t *ret;
    951 
    952 	assert(ind <= MALLOCX_ARENA_MAX);
    953 
    954 	ret = arenas[ind];
    955 	if (unlikely(ret == NULL)) {
    956 		ret = atomic_read_p((void *)&arenas[ind]);
    957 		if (init_if_missing && unlikely(ret == NULL))
    958 			ret = arena_init(tsdn, ind);
    959 	}
    960 	return (ret);
    961 }
    962 
    963 JEMALLOC_INLINE ticker_t *
    964 decay_ticker_get(tsd_t *tsd, unsigned ind)
    965 {
    966 	arena_tdata_t *tdata;
    967 
    968 	tdata = arena_tdata_get(tsd, ind, true);
    969 	if (unlikely(tdata == NULL))
    970 		return (NULL);
    971 	return (&tdata->decay_ticker);
    972 }
    973 #endif
    974 
    975 #include "jemalloc/internal/bitmap.h"
    976 /*
    977  * Include portions of arena.h interleaved with tcache.h in order to resolve
    978  * circular dependencies.
    979  */
    980 #define	JEMALLOC_ARENA_INLINE_A
    981 #include "jemalloc/internal/arena.h"
    982 #undef JEMALLOC_ARENA_INLINE_A
    983 #include "jemalloc/internal/tcache.h"
    984 #define	JEMALLOC_ARENA_INLINE_B
    985 #include "jemalloc/internal/arena.h"
    986 #undef JEMALLOC_ARENA_INLINE_B
    987 #include "jemalloc/internal/hash.h"
    988 #include "jemalloc/internal/quarantine.h"
    989 
    990 #ifndef JEMALLOC_ENABLE_INLINE
    991 arena_t	*iaalloc(const void *ptr);
    992 size_t	isalloc(tsdn_t *tsdn, const void *ptr, bool demote);
    993 void	*iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero,
    994     tcache_t *tcache, bool is_metadata, arena_t *arena, bool slow_path);
    995 void	*ialloc(tsd_t *tsd, size_t size, szind_t ind, bool zero,
    996     bool slow_path);
    997 void	*ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,
    998     tcache_t *tcache, bool is_metadata, arena_t *arena);
    999 void	*ipalloct(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,
   1000     tcache_t *tcache, arena_t *arena);
   1001 void	*ipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero);
   1002 size_t	ivsalloc(tsdn_t *tsdn, const void *ptr, bool demote);
   1003 size_t	u2rz(size_t usize);
   1004 size_t	p2rz(tsdn_t *tsdn, const void *ptr);
   1005 void	idalloctm(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool is_metadata,
   1006     bool slow_path);
   1007 void	idalloc(tsd_t *tsd, void *ptr);
   1008 void	iqalloc(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path);
   1009 void	isdalloct(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,
   1010     bool slow_path);
   1011 void	isqalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache,
   1012     bool slow_path);
   1013 void	*iralloct_realign(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,
   1014     size_t extra, size_t alignment, bool zero, tcache_t *tcache,
   1015     arena_t *arena);
   1016 void	*iralloct(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,
   1017     size_t alignment, bool zero, tcache_t *tcache, arena_t *arena);
   1018 void	*iralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,
   1019     size_t alignment, bool zero);
   1020 bool	ixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size,
   1021     size_t extra, size_t alignment, bool zero);
   1022 #endif
   1023 
   1024 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_C_))
   1025 JEMALLOC_ALWAYS_INLINE arena_t *
   1026 iaalloc(const void *ptr)
   1027 {
   1028 
   1029 	assert(ptr != NULL);
   1030 
   1031 	return (arena_aalloc(ptr));
   1032 }
   1033 
   1034 /*
   1035  * Typical usage:
   1036  *   tsdn_t *tsdn = [...]
   1037  *   void *ptr = [...]
   1038  *   size_t sz = isalloc(tsdn, ptr, config_prof);
   1039  */
   1040 JEMALLOC_ALWAYS_INLINE size_t
   1041 isalloc(tsdn_t *tsdn, const void *ptr, bool demote)
   1042 {
   1043 
   1044 	assert(ptr != NULL);
   1045 	/* Demotion only makes sense if config_prof is true. */
   1046 	assert(config_prof || !demote);
   1047 
   1048 	return (arena_salloc(tsdn, ptr, demote));
   1049 }
   1050 
   1051 JEMALLOC_ALWAYS_INLINE void *
   1052 iallocztm(tsdn_t *tsdn, size_t size, szind_t ind, bool zero, tcache_t *tcache,
   1053     bool is_metadata, arena_t *arena, bool slow_path)
   1054 {
   1055 	void *ret;
   1056 
   1057 	assert(size != 0);
   1058 	assert(!is_metadata || tcache == NULL);
   1059 	assert(!is_metadata || arena == NULL || arena->ind < narenas_auto);
   1060 
   1061 	ret = arena_malloc(tsdn, arena, size, ind, zero, tcache, slow_path);
   1062 	if (config_stats && is_metadata && likely(ret != NULL)) {
   1063 		arena_metadata_allocated_add(iaalloc(ret),
   1064 		    isalloc(tsdn, ret, config_prof));
   1065 	}
   1066 	return (ret);
   1067 }
   1068 
   1069 JEMALLOC_ALWAYS_INLINE void *
   1070 ialloc(tsd_t *tsd, size_t size, szind_t ind, bool zero, bool slow_path)
   1071 {
   1072 
   1073 	return (iallocztm(tsd_tsdn(tsd), size, ind, zero, tcache_get(tsd, true),
   1074 	    false, NULL, slow_path));
   1075 }
   1076 
   1077 JEMALLOC_ALWAYS_INLINE void *
   1078 ipallocztm(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,
   1079     tcache_t *tcache, bool is_metadata, arena_t *arena)
   1080 {
   1081 	void *ret;
   1082 
   1083 	assert(usize != 0);
   1084 	assert(usize == sa2u(usize, alignment));
   1085 	assert(!is_metadata || tcache == NULL);
   1086 	assert(!is_metadata || arena == NULL || arena->ind < narenas_auto);
   1087 
   1088 	ret = arena_palloc(tsdn, arena, usize, alignment, zero, tcache);
   1089 	assert(ALIGNMENT_ADDR2BASE(ret, alignment) == ret);
   1090 	if (config_stats && is_metadata && likely(ret != NULL)) {
   1091 		arena_metadata_allocated_add(iaalloc(ret), isalloc(tsdn, ret,
   1092 		    config_prof));
   1093 	}
   1094 	return (ret);
   1095 }
   1096 
   1097 JEMALLOC_ALWAYS_INLINE void *
   1098 ipalloct(tsdn_t *tsdn, size_t usize, size_t alignment, bool zero,
   1099     tcache_t *tcache, arena_t *arena)
   1100 {
   1101 
   1102 	return (ipallocztm(tsdn, usize, alignment, zero, tcache, false, arena));
   1103 }
   1104 
   1105 JEMALLOC_ALWAYS_INLINE void *
   1106 ipalloc(tsd_t *tsd, size_t usize, size_t alignment, bool zero)
   1107 {
   1108 
   1109 	return (ipallocztm(tsd_tsdn(tsd), usize, alignment, zero,
   1110 	    tcache_get(tsd, true), false, NULL));
   1111 }
   1112 
   1113 JEMALLOC_ALWAYS_INLINE size_t
   1114 ivsalloc(tsdn_t *tsdn, const void *ptr, bool demote)
   1115 {
   1116 	extent_node_t *node;
   1117 
   1118 	/* Return 0 if ptr is not within a chunk managed by jemalloc. */
   1119 	node = chunk_lookup(ptr, false);
   1120 	if (node == NULL)
   1121 		return (0);
   1122 	/* Only arena chunks should be looked up via interior pointers. */
   1123 	assert(extent_node_addr_get(node) == ptr ||
   1124 	    extent_node_achunk_get(node));
   1125 
   1126 	return (isalloc(tsdn, ptr, demote));
   1127 }
   1128 
   1129 JEMALLOC_INLINE size_t
   1130 u2rz(size_t usize)
   1131 {
   1132 	size_t ret;
   1133 
   1134 	if (usize <= SMALL_MAXCLASS) {
   1135 		szind_t binind = size2index(usize);
   1136 		ret = arena_bin_info[binind].redzone_size;
   1137 	} else
   1138 		ret = 0;
   1139 
   1140 	return (ret);
   1141 }
   1142 
   1143 JEMALLOC_INLINE size_t
   1144 p2rz(tsdn_t *tsdn, const void *ptr)
   1145 {
   1146 	size_t usize = isalloc(tsdn, ptr, false);
   1147 
   1148 	return (u2rz(usize));
   1149 }
   1150 
   1151 JEMALLOC_ALWAYS_INLINE void
   1152 idalloctm(tsdn_t *tsdn, void *ptr, tcache_t *tcache, bool is_metadata,
   1153     bool slow_path)
   1154 {
   1155 
   1156 	assert(ptr != NULL);
   1157 	assert(!is_metadata || tcache == NULL);
   1158 	assert(!is_metadata || iaalloc(ptr)->ind < narenas_auto);
   1159 	if (config_stats && is_metadata) {
   1160 		arena_metadata_allocated_sub(iaalloc(ptr), isalloc(tsdn, ptr,
   1161 		    config_prof));
   1162 	}
   1163 
   1164 	arena_dalloc(tsdn, ptr, tcache, slow_path);
   1165 }
   1166 
   1167 JEMALLOC_ALWAYS_INLINE void
   1168 idalloc(tsd_t *tsd, void *ptr)
   1169 {
   1170 
   1171 	idalloctm(tsd_tsdn(tsd), ptr, tcache_get(tsd, false), false, true);
   1172 }
   1173 
   1174 JEMALLOC_ALWAYS_INLINE void
   1175 iqalloc(tsd_t *tsd, void *ptr, tcache_t *tcache, bool slow_path)
   1176 {
   1177 
   1178 	if (slow_path && config_fill && unlikely(opt_quarantine))
   1179 		quarantine(tsd, ptr);
   1180 	else
   1181 		idalloctm(tsd_tsdn(tsd), ptr, tcache, false, slow_path);
   1182 }
   1183 
   1184 JEMALLOC_ALWAYS_INLINE void
   1185 isdalloct(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,
   1186     bool slow_path)
   1187 {
   1188 
   1189 	arena_sdalloc(tsdn, ptr, size, tcache, slow_path);
   1190 }
   1191 
   1192 JEMALLOC_ALWAYS_INLINE void
   1193 isqalloc(tsd_t *tsd, void *ptr, size_t size, tcache_t *tcache, bool slow_path)
   1194 {
   1195 
   1196 	if (slow_path && config_fill && unlikely(opt_quarantine))
   1197 		quarantine(tsd, ptr);
   1198 	else
   1199 		isdalloct(tsd_tsdn(tsd), ptr, size, tcache, slow_path);
   1200 }
   1201 
   1202 JEMALLOC_ALWAYS_INLINE void *
   1203 iralloct_realign(tsd_t *tsd, void *ptr, size_t oldsize, size_t size,
   1204     size_t extra, size_t alignment, bool zero, tcache_t *tcache, arena_t *arena)
   1205 {
   1206 	void *p;
   1207 	size_t usize, copysize;
   1208 
   1209 	usize = sa2u(size + extra, alignment);
   1210 	if (unlikely(usize == 0 || usize > HUGE_MAXCLASS))
   1211 		return (NULL);
   1212 	p = ipalloct(tsd_tsdn(tsd), usize, alignment, zero, tcache, arena);
   1213 	if (p == NULL) {
   1214 		if (extra == 0)
   1215 			return (NULL);
   1216 		/* Try again, without extra this time. */
   1217 		usize = sa2u(size, alignment);
   1218 		if (unlikely(usize == 0 || usize > HUGE_MAXCLASS))
   1219 			return (NULL);
   1220 		p = ipalloct(tsd_tsdn(tsd), usize, alignment, zero, tcache,
   1221 		    arena);
   1222 		if (p == NULL)
   1223 			return (NULL);
   1224 	}
   1225 	/*
   1226 	 * Copy at most size bytes (not size+extra), since the caller has no
   1227 	 * expectation that the extra bytes will be reliably preserved.
   1228 	 */
   1229 	copysize = (size < oldsize) ? size : oldsize;
   1230 	memcpy(p, ptr, copysize);
   1231 	isqalloc(tsd, ptr, oldsize, tcache, true);
   1232 	return (p);
   1233 }
   1234 
   1235 JEMALLOC_ALWAYS_INLINE void *
   1236 iralloct(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment,
   1237     bool zero, tcache_t *tcache, arena_t *arena)
   1238 {
   1239 
   1240 	assert(ptr != NULL);
   1241 	assert(size != 0);
   1242 
   1243 	if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))
   1244 	    != 0) {
   1245 		/*
   1246 		 * Existing object alignment is inadequate; allocate new space
   1247 		 * and copy.
   1248 		 */
   1249 		return (iralloct_realign(tsd, ptr, oldsize, size, 0, alignment,
   1250 		    zero, tcache, arena));
   1251 	}
   1252 
   1253 	return (arena_ralloc(tsd, arena, ptr, oldsize, size, alignment, zero,
   1254 	    tcache));
   1255 }
   1256 
   1257 JEMALLOC_ALWAYS_INLINE void *
   1258 iralloc(tsd_t *tsd, void *ptr, size_t oldsize, size_t size, size_t alignment,
   1259     bool zero)
   1260 {
   1261 
   1262 	return (iralloct(tsd, ptr, oldsize, size, alignment, zero,
   1263 	    tcache_get(tsd, true), NULL));
   1264 }
   1265 
   1266 JEMALLOC_ALWAYS_INLINE bool
   1267 ixalloc(tsdn_t *tsdn, void *ptr, size_t oldsize, size_t size, size_t extra,
   1268     size_t alignment, bool zero)
   1269 {
   1270 
   1271 	assert(ptr != NULL);
   1272 	assert(size != 0);
   1273 
   1274 	if (alignment != 0 && ((uintptr_t)ptr & ((uintptr_t)alignment-1))
   1275 	    != 0) {
   1276 		/* Existing object alignment is inadequate. */
   1277 		return (true);
   1278 	}
   1279 
   1280 	return (arena_ralloc_no_move(tsdn, ptr, oldsize, size, extra, zero));
   1281 }
   1282 #endif
   1283 
   1284 #include "jemalloc/internal/prof.h"
   1285 
   1286 #undef JEMALLOC_H_INLINES
   1287 /******************************************************************************/
   1288 #endif /* JEMALLOC_INTERNAL_H */
   1289