Home | History | Annotate | Download | only in internal
      1 /******************************************************************************/
      2 #ifdef JEMALLOC_H_TYPES
      3 
      4 /*
      5  * RUN_MAX_OVRHD indicates maximum desired run header overhead.  Runs are sized
      6  * as small as possible such that this setting is still honored, without
      7  * violating other constraints.  The goal is to make runs as small as possible
      8  * without exceeding a per run external fragmentation threshold.
      9  *
     10  * We use binary fixed point math for overhead computations, where the binary
     11  * point is implicitly RUN_BFP bits to the left.
     12  *
     13  * Note that it is possible to set RUN_MAX_OVRHD low enough that it cannot be
     14  * honored for some/all object sizes, since when heap profiling is enabled
     15  * there is one pointer of header overhead per object (plus a constant).  This
     16  * constraint is relaxed (ignored) for runs that are so small that the
     17  * per-region overhead is greater than:
     18  *
     19  *   (RUN_MAX_OVRHD / (reg_interval << (3+RUN_BFP))
     20  */
     21 #define	RUN_BFP			12
     22 /*                                    \/   Implicit binary fixed point. */
     23 #define	RUN_MAX_OVRHD		0x0000003dU
     24 #define	RUN_MAX_OVRHD_RELAX	0x00001800U
     25 
     26 /* Maximum number of regions in one run. */
     27 #define	LG_RUN_MAXREGS		11
     28 #define	RUN_MAXREGS		(1U << LG_RUN_MAXREGS)
     29 
     30 /*
     31  * Minimum redzone size.  Redzones may be larger than this if necessary to
     32  * preserve region alignment.
     33  */
     34 #define	REDZONE_MINSIZE		16
     35 
     36 /*
     37  * The minimum ratio of active:dirty pages per arena is computed as:
     38  *
     39  *   (nactive >> opt_lg_dirty_mult) >= ndirty
     40  *
     41  * So, supposing that opt_lg_dirty_mult is 3, there can be no less than 8 times
     42  * as many active pages as dirty pages.
     43  */
     44 #define	LG_DIRTY_MULT_DEFAULT	3
     45 
     46 typedef struct arena_chunk_map_s arena_chunk_map_t;
     47 typedef struct arena_chunk_s arena_chunk_t;
     48 typedef struct arena_run_s arena_run_t;
     49 typedef struct arena_bin_info_s arena_bin_info_t;
     50 typedef struct arena_bin_s arena_bin_t;
     51 typedef struct arena_s arena_t;
     52 
     53 #endif /* JEMALLOC_H_TYPES */
     54 /******************************************************************************/
     55 #ifdef JEMALLOC_H_STRUCTS
     56 
     57 /* Each element of the chunk map corresponds to one page within the chunk. */
     58 struct arena_chunk_map_s {
     59 #ifndef JEMALLOC_PROF
     60 	/*
     61 	 * Overlay prof_ctx in order to allow it to be referenced by dead code.
     62 	 * Such antics aren't warranted for per arena data structures, but
     63 	 * chunk map overhead accounts for a percentage of memory, rather than
     64 	 * being just a fixed cost.
     65 	 */
     66 	union {
     67 #endif
     68 	union {
     69 		/*
     70 		 * Linkage for run trees.  There are two disjoint uses:
     71 		 *
     72 		 * 1) arena_t's runs_avail tree.
     73 		 * 2) arena_run_t conceptually uses this linkage for in-use
     74 		 *    non-full runs, rather than directly embedding linkage.
     75 		 */
     76 		rb_node(arena_chunk_map_t)	rb_link;
     77 		/*
     78 		 * List of runs currently in purgatory.  arena_chunk_purge()
     79 		 * temporarily allocates runs that contain dirty pages while
     80 		 * purging, so that other threads cannot use the runs while the
     81 		 * purging thread is operating without the arena lock held.
     82 		 */
     83 		ql_elm(arena_chunk_map_t)	ql_link;
     84 	}				u;
     85 
     86 	/* Profile counters, used for large object runs. */
     87 	prof_ctx_t			*prof_ctx;
     88 #ifndef JEMALLOC_PROF
     89 	}; /* union { ... }; */
     90 #endif
     91 
     92 	/*
     93 	 * Run address (or size) and various flags are stored together.  The bit
     94 	 * layout looks like (assuming 32-bit system):
     95 	 *
     96 	 *   ???????? ???????? ????nnnn nnnndula
     97 	 *
     98 	 * ? : Unallocated: Run address for first/last pages, unset for internal
     99 	 *                  pages.
    100 	 *     Small: Run page offset.
    101 	 *     Large: Run size for first page, unset for trailing pages.
    102 	 * n : binind for small size class, BININD_INVALID for large size class.
    103 	 * d : dirty?
    104 	 * u : unzeroed?
    105 	 * l : large?
    106 	 * a : allocated?
    107 	 *
    108 	 * Following are example bit patterns for the three types of runs.
    109 	 *
    110 	 * p : run page offset
    111 	 * s : run size
    112 	 * n : binind for size class; large objects set these to BININD_INVALID
    113 	 * x : don't care
    114 	 * - : 0
    115 	 * + : 1
    116 	 * [DULA] : bit set
    117 	 * [dula] : bit unset
    118 	 *
    119 	 *   Unallocated (clean):
    120 	 *     ssssssss ssssssss ssss++++ ++++du-a
    121 	 *     xxxxxxxx xxxxxxxx xxxxxxxx xxxx-Uxx
    122 	 *     ssssssss ssssssss ssss++++ ++++dU-a
    123 	 *
    124 	 *   Unallocated (dirty):
    125 	 *     ssssssss ssssssss ssss++++ ++++D--a
    126 	 *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    127 	 *     ssssssss ssssssss ssss++++ ++++D--a
    128 	 *
    129 	 *   Small:
    130 	 *     pppppppp pppppppp ppppnnnn nnnnd--A
    131 	 *     pppppppp pppppppp ppppnnnn nnnn---A
    132 	 *     pppppppp pppppppp ppppnnnn nnnnd--A
    133 	 *
    134 	 *   Large:
    135 	 *     ssssssss ssssssss ssss++++ ++++D-LA
    136 	 *     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
    137 	 *     -------- -------- ----++++ ++++D-LA
    138 	 *
    139 	 *   Large (sampled, size <= PAGE):
    140 	 *     ssssssss ssssssss ssssnnnn nnnnD-LA
    141 	 *
    142 	 *   Large (not sampled, size == PAGE):
    143 	 *     ssssssss ssssssss ssss++++ ++++D-LA
    144 	 */
    145 	size_t				bits;
    146 #define	CHUNK_MAP_BININD_SHIFT	4
    147 #define	BININD_INVALID		((size_t)0xffU)
    148 /*     CHUNK_MAP_BININD_MASK == (BININD_INVALID << CHUNK_MAP_BININD_SHIFT) */
    149 #define	CHUNK_MAP_BININD_MASK	((size_t)0xff0U)
    150 #define	CHUNK_MAP_BININD_INVALID CHUNK_MAP_BININD_MASK
    151 #define	CHUNK_MAP_FLAGS_MASK	((size_t)0xcU)
    152 #define	CHUNK_MAP_DIRTY		((size_t)0x8U)
    153 #define	CHUNK_MAP_UNZEROED	((size_t)0x4U)
    154 #define	CHUNK_MAP_LARGE		((size_t)0x2U)
    155 #define	CHUNK_MAP_ALLOCATED	((size_t)0x1U)
    156 #define	CHUNK_MAP_KEY		CHUNK_MAP_ALLOCATED
    157 };
    158 typedef rb_tree(arena_chunk_map_t) arena_avail_tree_t;
    159 typedef rb_tree(arena_chunk_map_t) arena_run_tree_t;
    160 typedef ql_head(arena_chunk_map_t) arena_chunk_mapelms_t;
    161 
    162 /* Arena chunk header. */
    163 struct arena_chunk_s {
    164 	/* Arena that owns the chunk. */
    165 	arena_t			*arena;
    166 
    167 	/* Linkage for tree of arena chunks that contain dirty runs. */
    168 	rb_node(arena_chunk_t)	dirty_link;
    169 
    170 	/* Number of dirty pages. */
    171 	size_t			ndirty;
    172 
    173 	/* Number of available runs. */
    174 	size_t			nruns_avail;
    175 
    176 	/*
    177 	 * Number of available run adjacencies that purging could coalesce.
    178 	 * Clean and dirty available runs are not coalesced, which causes
    179 	 * virtual memory fragmentation.  The ratio of
    180 	 * (nruns_avail-nruns_adjac):nruns_adjac is used for tracking this
    181 	 * fragmentation.
    182 	 */
    183 	size_t			nruns_adjac;
    184 
    185 	/*
    186 	 * Map of pages within chunk that keeps track of free/large/small.  The
    187 	 * first map_bias entries are omitted, since the chunk header does not
    188 	 * need to be tracked in the map.  This omission saves a header page
    189 	 * for common chunk sizes (e.g. 4 MiB).
    190 	 */
    191 	arena_chunk_map_t	map[1]; /* Dynamically sized. */
    192 };
    193 typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
    194 
    195 struct arena_run_s {
    196 	/* Bin this run is associated with. */
    197 	arena_bin_t	*bin;
    198 
    199 	/* Index of next region that has never been allocated, or nregs. */
    200 	uint32_t	nextind;
    201 
    202 	/* Number of free regions in run. */
    203 	unsigned	nfree;
    204 };
    205 
    206 /*
    207  * Read-only information associated with each element of arena_t's bins array
    208  * is stored separately, partly to reduce memory usage (only one copy, rather
    209  * than one per arena), but mainly to avoid false cacheline sharing.
    210  *
    211  * Each run has the following layout:
    212  *
    213  *               /--------------------\
    214  *               | arena_run_t header |
    215  *               | ...                |
    216  * bitmap_offset | bitmap             |
    217  *               | ...                |
    218  *               |--------------------|
    219  *               | redzone            |
    220  *   reg0_offset | region 0           |
    221  *               | redzone            |
    222  *               |--------------------| \
    223  *               | redzone            | |
    224  *               | region 1           |  > reg_interval
    225  *               | redzone            | /
    226  *               |--------------------|
    227  *               | ...                |
    228  *               | ...                |
    229  *               | ...                |
    230  *               |--------------------|
    231  *               | redzone            |
    232  *               | region nregs-1     |
    233  *               | redzone            |
    234  *               |--------------------|
    235  *               | alignment pad?     |
    236  *               \--------------------/
    237  *
    238  * reg_interval has at least the same minimum alignment as reg_size; this
    239  * preserves the alignment constraint that sa2u() depends on.  Alignment pad is
    240  * either 0 or redzone_size; it is present only if needed to align reg0_offset.
    241  */
    242 struct arena_bin_info_s {
    243 	/* Size of regions in a run for this bin's size class. */
    244 	size_t		reg_size;
    245 
    246 	/* Redzone size. */
    247 	size_t		redzone_size;
    248 
    249 	/* Interval between regions (reg_size + (redzone_size << 1)). */
    250 	size_t		reg_interval;
    251 
    252 	/* Total size of a run for this bin's size class. */
    253 	size_t		run_size;
    254 
    255 	/* Total number of regions in a run for this bin's size class. */
    256 	uint32_t	nregs;
    257 
    258 	/*
    259 	 * Offset of first bitmap_t element in a run header for this bin's size
    260 	 * class.
    261 	 */
    262 	uint32_t	bitmap_offset;
    263 
    264 	/*
    265 	 * Metadata used to manipulate bitmaps for runs associated with this
    266 	 * bin.
    267 	 */
    268 	bitmap_info_t	bitmap_info;
    269 
    270 	/* Offset of first region in a run for this bin's size class. */
    271 	uint32_t	reg0_offset;
    272 };
    273 
    274 struct arena_bin_s {
    275 	/*
    276 	 * All operations on runcur, runs, and stats require that lock be
    277 	 * locked.  Run allocation/deallocation are protected by the arena lock,
    278 	 * which may be acquired while holding one or more bin locks, but not
    279 	 * vise versa.
    280 	 */
    281 	malloc_mutex_t	lock;
    282 
    283 	/*
    284 	 * Current run being used to service allocations of this bin's size
    285 	 * class.
    286 	 */
    287 	arena_run_t	*runcur;
    288 
    289 	/*
    290 	 * Tree of non-full runs.  This tree is used when looking for an
    291 	 * existing run when runcur is no longer usable.  We choose the
    292 	 * non-full run that is lowest in memory; this policy tends to keep
    293 	 * objects packed well, and it can also help reduce the number of
    294 	 * almost-empty chunks.
    295 	 */
    296 	arena_run_tree_t runs;
    297 
    298 	/* Bin statistics. */
    299 	malloc_bin_stats_t stats;
    300 };
    301 
    302 struct arena_s {
    303 	/* This arena's index within the arenas array. */
    304 	unsigned		ind;
    305 
    306 	/*
    307 	 * Number of threads currently assigned to this arena.  This field is
    308 	 * protected by arenas_lock.
    309 	 */
    310 	unsigned		nthreads;
    311 
    312 	/*
    313 	 * There are three classes of arena operations from a locking
    314 	 * perspective:
    315 	 * 1) Thread asssignment (modifies nthreads) is protected by
    316 	 *    arenas_lock.
    317 	 * 2) Bin-related operations are protected by bin locks.
    318 	 * 3) Chunk- and run-related operations are protected by this mutex.
    319 	 */
    320 	malloc_mutex_t		lock;
    321 
    322 	arena_stats_t		stats;
    323 	/*
    324 	 * List of tcaches for extant threads associated with this arena.
    325 	 * Stats from these are merged incrementally, and at exit.
    326 	 */
    327 	ql_head(tcache_t)	tcache_ql;
    328 
    329 	uint64_t		prof_accumbytes;
    330 
    331 	dss_prec_t		dss_prec;
    332 
    333 	/* Tree of dirty-page-containing chunks this arena manages. */
    334 	arena_chunk_tree_t	chunks_dirty;
    335 
    336 	/*
    337 	 * In order to avoid rapid chunk allocation/deallocation when an arena
    338 	 * oscillates right on the cusp of needing a new chunk, cache the most
    339 	 * recently freed chunk.  The spare is left in the arena's chunk trees
    340 	 * until it is deleted.
    341 	 *
    342 	 * There is one spare chunk per arena, rather than one spare total, in
    343 	 * order to avoid interactions between multiple threads that could make
    344 	 * a single spare inadequate.
    345 	 */
    346 	arena_chunk_t		*spare;
    347 
    348 	/* Number of pages in active runs and huge regions. */
    349 	size_t			nactive;
    350 
    351 	/*
    352 	 * Current count of pages within unused runs that are potentially
    353 	 * dirty, and for which madvise(... MADV_DONTNEED) has not been called.
    354 	 * By tracking this, we can institute a limit on how much dirty unused
    355 	 * memory is mapped for each arena.
    356 	 */
    357 	size_t			ndirty;
    358 
    359 	/*
    360 	 * Approximate number of pages being purged.  It is possible for
    361 	 * multiple threads to purge dirty pages concurrently, and they use
    362 	 * npurgatory to indicate the total number of pages all threads are
    363 	 * attempting to purge.
    364 	 */
    365 	size_t			npurgatory;
    366 
    367 	/*
    368 	 * Size/address-ordered trees of this arena's available runs.  The trees
    369 	 * are used for first-best-fit run allocation.
    370 	 */
    371 	arena_avail_tree_t	runs_avail;
    372 
    373 	/*
    374 	 * user-configureable chunk allocation and deallocation functions.
    375 	 */
    376 	chunk_alloc_t		*chunk_alloc;
    377 	chunk_dalloc_t		*chunk_dalloc;
    378 
    379 	/* bins is used to store trees of free regions. */
    380 	arena_bin_t		bins[NBINS];
    381 };
    382 
    383 #endif /* JEMALLOC_H_STRUCTS */
    384 /******************************************************************************/
    385 #ifdef JEMALLOC_H_EXTERNS
    386 
    387 extern ssize_t	opt_lg_dirty_mult;
    388 /*
    389  * small_size2bin_tab is a compact lookup table that rounds request sizes up to
    390  * size classes.  In order to reduce cache footprint, the table is compressed,
    391  * and all accesses are via small_size2bin().
    392  */
    393 extern uint8_t const	small_size2bin_tab[];
    394 /*
    395  * small_bin2size_tab duplicates information in arena_bin_info, but in a const
    396  * array, for which it is easier for the compiler to optimize repeated
    397  * dereferences.
    398  */
    399 extern uint32_t const	small_bin2size_tab[NBINS];
    400 
    401 extern arena_bin_info_t	arena_bin_info[NBINS];
    402 
    403 /* Number of large size classes. */
    404 #define			nlclasses (chunk_npages - map_bias)
    405 
    406 void	*arena_chunk_alloc_huge(arena_t *arena, size_t size, size_t alignment,
    407     bool *zero);
    408 void	arena_chunk_dalloc_huge(arena_t *arena, void *chunk, size_t size);
    409 void	arena_purge_all(arena_t *arena);
    410 void	arena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin,
    411     size_t binind, uint64_t prof_accumbytes);
    412 void	arena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info,
    413     bool zero);
    414 #ifdef JEMALLOC_JET
    415 typedef void (arena_redzone_corruption_t)(void *, size_t, bool, size_t,
    416     uint8_t);
    417 extern arena_redzone_corruption_t *arena_redzone_corruption;
    418 typedef void (arena_dalloc_junk_small_t)(void *, arena_bin_info_t *);
    419 extern arena_dalloc_junk_small_t *arena_dalloc_junk_small;
    420 #else
    421 void	arena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info);
    422 #endif
    423 void	arena_quarantine_junk_small(void *ptr, size_t usize);
    424 void	*arena_malloc_small(arena_t *arena, size_t size, bool zero);
    425 void	*arena_malloc_large(arena_t *arena, size_t size, bool zero);
    426 void	*arena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero);
    427 void	arena_prof_promoted(const void *ptr, size_t size);
    428 void	arena_dalloc_bin_locked(arena_t *arena, arena_chunk_t *chunk, void *ptr,
    429     arena_chunk_map_t *mapelm);
    430 void	arena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr,
    431     size_t pageind, arena_chunk_map_t *mapelm);
    432 void	arena_dalloc_small(arena_t *arena, arena_chunk_t *chunk, void *ptr,
    433     size_t pageind);
    434 #ifdef JEMALLOC_JET
    435 typedef void (arena_dalloc_junk_large_t)(void *, size_t);
    436 extern arena_dalloc_junk_large_t *arena_dalloc_junk_large;
    437 #endif
    438 void	arena_dalloc_large_locked(arena_t *arena, arena_chunk_t *chunk,
    439     void *ptr);
    440 void	arena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr);
    441 #ifdef JEMALLOC_JET
    442 typedef void (arena_ralloc_junk_large_t)(void *, size_t, size_t);
    443 extern arena_ralloc_junk_large_t *arena_ralloc_junk_large;
    444 #endif
    445 bool	arena_ralloc_no_move(void *ptr, size_t oldsize, size_t size,
    446     size_t extra, bool zero);
    447 void	*arena_ralloc(arena_t *arena, void *ptr, size_t oldsize, size_t size,
    448     size_t extra, size_t alignment, bool zero, bool try_tcache_alloc,
    449     bool try_tcache_dalloc);
    450 dss_prec_t	arena_dss_prec_get(arena_t *arena);
    451 bool	arena_dss_prec_set(arena_t *arena, dss_prec_t dss_prec);
    452 void	arena_stats_merge(arena_t *arena, const char **dss, size_t *nactive,
    453     size_t *ndirty, arena_stats_t *astats, malloc_bin_stats_t *bstats,
    454     malloc_large_stats_t *lstats);
    455 bool	arena_new(arena_t *arena, unsigned ind);
    456 void	arena_boot(void);
    457 void	arena_prefork(arena_t *arena);
    458 void	arena_postfork_parent(arena_t *arena);
    459 void	arena_postfork_child(arena_t *arena);
    460 
    461 #endif /* JEMALLOC_H_EXTERNS */
    462 /******************************************************************************/
    463 #ifdef JEMALLOC_H_INLINES
    464 
    465 #ifndef JEMALLOC_ENABLE_INLINE
    466 size_t	small_size2bin_compute(size_t size);
    467 size_t	small_size2bin_lookup(size_t size);
    468 size_t	small_size2bin(size_t size);
    469 size_t	small_bin2size_compute(size_t binind);
    470 size_t	small_bin2size_lookup(size_t binind);
    471 size_t	small_bin2size(size_t binind);
    472 size_t	small_s2u_compute(size_t size);
    473 size_t	small_s2u_lookup(size_t size);
    474 size_t	small_s2u(size_t size);
    475 arena_chunk_map_t	*arena_mapp_get(arena_chunk_t *chunk, size_t pageind);
    476 size_t	*arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind);
    477 size_t	arena_mapbitsp_read(size_t *mapbitsp);
    478 size_t	arena_mapbits_get(arena_chunk_t *chunk, size_t pageind);
    479 size_t	arena_mapbits_unallocated_size_get(arena_chunk_t *chunk,
    480     size_t pageind);
    481 size_t	arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind);
    482 size_t	arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind);
    483 size_t	arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind);
    484 size_t	arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind);
    485 size_t	arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind);
    486 size_t	arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind);
    487 size_t	arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind);
    488 void	arena_mapbitsp_write(size_t *mapbitsp, size_t mapbits);
    489 void	arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind,
    490     size_t size, size_t flags);
    491 void	arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,
    492     size_t size);
    493 void	arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind,
    494     size_t size, size_t flags);
    495 void	arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,
    496     size_t binind);
    497 void	arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind,
    498     size_t runind, size_t binind, size_t flags);
    499 void	arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,
    500     size_t unzeroed);
    501 bool	arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes);
    502 bool	arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes);
    503 bool	arena_prof_accum(arena_t *arena, uint64_t accumbytes);
    504 size_t	arena_ptr_small_binind_get(const void *ptr, size_t mapbits);
    505 size_t	arena_bin_index(arena_t *arena, arena_bin_t *bin);
    506 unsigned	arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info,
    507     const void *ptr);
    508 prof_ctx_t	*arena_prof_ctx_get(const void *ptr);
    509 void	arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx);
    510 void	*arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache);
    511 size_t	arena_salloc(const void *ptr, bool demote);
    512 void	arena_dalloc(arena_chunk_t *chunk, void *ptr, bool try_tcache);
    513 #endif
    514 
    515 #if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_ARENA_C_))
    516 #  ifdef JEMALLOC_ARENA_INLINE_A
    517 JEMALLOC_INLINE size_t
    518 small_size2bin_compute(size_t size)
    519 {
    520 #if (NTBINS != 0)
    521 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
    522 		size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
    523 		size_t lg_ceil = lg_floor(pow2_ceil(size));
    524 		return (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin);
    525 	} else
    526 #endif
    527 	{
    528 		size_t x = lg_floor((size<<1)-1);
    529 		size_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :
    530 		    x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);
    531 		size_t grp = shift << LG_SIZE_CLASS_GROUP;
    532 
    533 		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
    534 		    ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
    535 
    536 		size_t delta_inverse_mask = ZI(-1) << lg_delta;
    537 		size_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) &
    538 		    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
    539 
    540 		size_t bin = NTBINS + grp + mod;
    541 		return (bin);
    542 	}
    543 }
    544 
    545 JEMALLOC_ALWAYS_INLINE size_t
    546 small_size2bin_lookup(size_t size)
    547 {
    548 
    549 	assert(size <= LOOKUP_MAXCLASS);
    550 	{
    551 		size_t ret = ((size_t)(small_size2bin_tab[(size-1) >>
    552 		    LG_TINY_MIN]));
    553 		assert(ret == small_size2bin_compute(size));
    554 		return (ret);
    555 	}
    556 }
    557 
    558 JEMALLOC_ALWAYS_INLINE size_t
    559 small_size2bin(size_t size)
    560 {
    561 
    562 	assert(size > 0);
    563 	if (size <= LOOKUP_MAXCLASS)
    564 		return (small_size2bin_lookup(size));
    565 	else
    566 		return (small_size2bin_compute(size));
    567 }
    568 
    569 JEMALLOC_INLINE size_t
    570 small_bin2size_compute(size_t binind)
    571 {
    572 #if (NTBINS > 0)
    573 	if (binind < NTBINS)
    574 		return (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + binind));
    575 	else
    576 #endif
    577 	{
    578 		size_t reduced_binind = binind - NTBINS;
    579 		size_t grp = reduced_binind >> LG_SIZE_CLASS_GROUP;
    580 		size_t mod = reduced_binind & ((ZU(1) << LG_SIZE_CLASS_GROUP) -
    581 		    1);
    582 
    583 		size_t grp_size_mask = ~((!!grp)-1);
    584 		size_t grp_size = ((ZU(1) << (LG_QUANTUM +
    585 		    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;
    586 
    587 		size_t shift = (grp == 0) ? 1 : grp;
    588 		size_t lg_delta = shift + (LG_QUANTUM-1);
    589 		size_t mod_size = (mod+1) << lg_delta;
    590 
    591 		size_t usize = grp_size + mod_size;
    592 		return (usize);
    593 	}
    594 }
    595 
    596 JEMALLOC_ALWAYS_INLINE size_t
    597 small_bin2size_lookup(size_t binind)
    598 {
    599 
    600 	assert(binind < NBINS);
    601 	{
    602 		size_t ret = ((size_t)(small_bin2size_tab[binind]));
    603 		assert(ret == small_bin2size_compute(binind));
    604 		return (ret);
    605 	}
    606 }
    607 
    608 JEMALLOC_ALWAYS_INLINE size_t
    609 small_bin2size(size_t binind)
    610 {
    611 
    612 	return (small_bin2size_lookup(binind));
    613 }
    614 
    615 JEMALLOC_ALWAYS_INLINE size_t
    616 small_s2u_compute(size_t size)
    617 {
    618 #if (NTBINS > 0)
    619 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
    620 		size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
    621 		size_t lg_ceil = lg_floor(pow2_ceil(size));
    622 		return (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) :
    623 		    (ZU(1) << lg_ceil));
    624 	} else
    625 #endif
    626 	{
    627 		size_t x = lg_floor((size<<1)-1);
    628 		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
    629 		    ?  LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
    630 		size_t delta = ZU(1) << lg_delta;
    631 		size_t delta_mask = delta - 1;
    632 		size_t usize = (size + delta_mask) & ~delta_mask;
    633 		return (usize);
    634 	}
    635 }
    636 
    637 JEMALLOC_ALWAYS_INLINE size_t
    638 small_s2u_lookup(size_t size)
    639 {
    640 	size_t ret = (small_bin2size(small_size2bin(size)));
    641 
    642 	assert(ret == small_s2u_compute(size));
    643 	return (ret);
    644 }
    645 
    646 JEMALLOC_ALWAYS_INLINE size_t
    647 small_s2u(size_t size)
    648 {
    649 
    650 	assert(size > 0);
    651 	if (size <= LOOKUP_MAXCLASS)
    652 		return (small_s2u_lookup(size));
    653 	else
    654 		return (small_s2u_compute(size));
    655 }
    656 #  endif /* JEMALLOC_ARENA_INLINE_A */
    657 
    658 #  ifdef JEMALLOC_ARENA_INLINE_B
    659 JEMALLOC_ALWAYS_INLINE arena_chunk_map_t *
    660 arena_mapp_get(arena_chunk_t *chunk, size_t pageind)
    661 {
    662 
    663 	assert(pageind >= map_bias);
    664 	assert(pageind < chunk_npages);
    665 
    666 	return (&chunk->map[pageind-map_bias]);
    667 }
    668 
    669 JEMALLOC_ALWAYS_INLINE size_t *
    670 arena_mapbitsp_get(arena_chunk_t *chunk, size_t pageind)
    671 {
    672 
    673 	return (&arena_mapp_get(chunk, pageind)->bits);
    674 }
    675 
    676 JEMALLOC_ALWAYS_INLINE size_t
    677 arena_mapbitsp_read(size_t *mapbitsp)
    678 {
    679 
    680 	return (*mapbitsp);
    681 }
    682 
    683 JEMALLOC_ALWAYS_INLINE size_t
    684 arena_mapbits_get(arena_chunk_t *chunk, size_t pageind)
    685 {
    686 
    687 	return (arena_mapbitsp_read(arena_mapbitsp_get(chunk, pageind)));
    688 }
    689 
    690 JEMALLOC_ALWAYS_INLINE size_t
    691 arena_mapbits_unallocated_size_get(arena_chunk_t *chunk, size_t pageind)
    692 {
    693 	size_t mapbits;
    694 
    695 	mapbits = arena_mapbits_get(chunk, pageind);
    696 	assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);
    697 	return (mapbits & ~PAGE_MASK);
    698 }
    699 
    700 JEMALLOC_ALWAYS_INLINE size_t
    701 arena_mapbits_large_size_get(arena_chunk_t *chunk, size_t pageind)
    702 {
    703 	size_t mapbits;
    704 
    705 	mapbits = arena_mapbits_get(chunk, pageind);
    706 	assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==
    707 	    (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED));
    708 	return (mapbits & ~PAGE_MASK);
    709 }
    710 
    711 JEMALLOC_ALWAYS_INLINE size_t
    712 arena_mapbits_small_runind_get(arena_chunk_t *chunk, size_t pageind)
    713 {
    714 	size_t mapbits;
    715 
    716 	mapbits = arena_mapbits_get(chunk, pageind);
    717 	assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) ==
    718 	    CHUNK_MAP_ALLOCATED);
    719 	return (mapbits >> LG_PAGE);
    720 }
    721 
    722 JEMALLOC_ALWAYS_INLINE size_t
    723 arena_mapbits_binind_get(arena_chunk_t *chunk, size_t pageind)
    724 {
    725 	size_t mapbits;
    726 	size_t binind;
    727 
    728 	mapbits = arena_mapbits_get(chunk, pageind);
    729 	binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;
    730 	assert(binind < NBINS || binind == BININD_INVALID);
    731 	return (binind);
    732 }
    733 
    734 JEMALLOC_ALWAYS_INLINE size_t
    735 arena_mapbits_dirty_get(arena_chunk_t *chunk, size_t pageind)
    736 {
    737 	size_t mapbits;
    738 
    739 	mapbits = arena_mapbits_get(chunk, pageind);
    740 	return (mapbits & CHUNK_MAP_DIRTY);
    741 }
    742 
    743 JEMALLOC_ALWAYS_INLINE size_t
    744 arena_mapbits_unzeroed_get(arena_chunk_t *chunk, size_t pageind)
    745 {
    746 	size_t mapbits;
    747 
    748 	mapbits = arena_mapbits_get(chunk, pageind);
    749 	return (mapbits & CHUNK_MAP_UNZEROED);
    750 }
    751 
    752 JEMALLOC_ALWAYS_INLINE size_t
    753 arena_mapbits_large_get(arena_chunk_t *chunk, size_t pageind)
    754 {
    755 	size_t mapbits;
    756 
    757 	mapbits = arena_mapbits_get(chunk, pageind);
    758 	return (mapbits & CHUNK_MAP_LARGE);
    759 }
    760 
    761 JEMALLOC_ALWAYS_INLINE size_t
    762 arena_mapbits_allocated_get(arena_chunk_t *chunk, size_t pageind)
    763 {
    764 	size_t mapbits;
    765 
    766 	mapbits = arena_mapbits_get(chunk, pageind);
    767 	return (mapbits & CHUNK_MAP_ALLOCATED);
    768 }
    769 
    770 JEMALLOC_ALWAYS_INLINE void
    771 arena_mapbitsp_write(size_t *mapbitsp, size_t mapbits)
    772 {
    773 
    774 	*mapbitsp = mapbits;
    775 }
    776 
    777 JEMALLOC_ALWAYS_INLINE void
    778 arena_mapbits_unallocated_set(arena_chunk_t *chunk, size_t pageind, size_t size,
    779     size_t flags)
    780 {
    781 	size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
    782 
    783 	assert((size & PAGE_MASK) == 0);
    784 	assert((flags & ~CHUNK_MAP_FLAGS_MASK) == 0);
    785 	assert((flags & (CHUNK_MAP_DIRTY|CHUNK_MAP_UNZEROED)) == flags);
    786 	arena_mapbitsp_write(mapbitsp, size | CHUNK_MAP_BININD_INVALID | flags);
    787 }
    788 
    789 JEMALLOC_ALWAYS_INLINE void
    790 arena_mapbits_unallocated_size_set(arena_chunk_t *chunk, size_t pageind,
    791     size_t size)
    792 {
    793 	size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
    794 	size_t mapbits = arena_mapbitsp_read(mapbitsp);
    795 
    796 	assert((size & PAGE_MASK) == 0);
    797 	assert((mapbits & (CHUNK_MAP_LARGE|CHUNK_MAP_ALLOCATED)) == 0);
    798 	arena_mapbitsp_write(mapbitsp, size | (mapbits & PAGE_MASK));
    799 }
    800 
    801 JEMALLOC_ALWAYS_INLINE void
    802 arena_mapbits_large_set(arena_chunk_t *chunk, size_t pageind, size_t size,
    803     size_t flags)
    804 {
    805 	size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
    806 	size_t mapbits = arena_mapbitsp_read(mapbitsp);
    807 	size_t unzeroed;
    808 
    809 	assert((size & PAGE_MASK) == 0);
    810 	assert((flags & CHUNK_MAP_DIRTY) == flags);
    811 	unzeroed = mapbits & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */
    812 	arena_mapbitsp_write(mapbitsp, size | CHUNK_MAP_BININD_INVALID | flags
    813 	    | unzeroed | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED);
    814 }
    815 
    816 JEMALLOC_ALWAYS_INLINE void
    817 arena_mapbits_large_binind_set(arena_chunk_t *chunk, size_t pageind,
    818     size_t binind)
    819 {
    820 	size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
    821 	size_t mapbits = arena_mapbitsp_read(mapbitsp);
    822 
    823 	assert(binind <= BININD_INVALID);
    824 	assert(arena_mapbits_large_size_get(chunk, pageind) == PAGE);
    825 	arena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_BININD_MASK) |
    826 	    (binind << CHUNK_MAP_BININD_SHIFT));
    827 }
    828 
    829 JEMALLOC_ALWAYS_INLINE void
    830 arena_mapbits_small_set(arena_chunk_t *chunk, size_t pageind, size_t runind,
    831     size_t binind, size_t flags)
    832 {
    833 	size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
    834 	size_t mapbits = arena_mapbitsp_read(mapbitsp);
    835 	size_t unzeroed;
    836 
    837 	assert(binind < BININD_INVALID);
    838 	assert(pageind - runind >= map_bias);
    839 	assert((flags & CHUNK_MAP_DIRTY) == flags);
    840 	unzeroed = mapbits & CHUNK_MAP_UNZEROED; /* Preserve unzeroed. */
    841 	arena_mapbitsp_write(mapbitsp, (runind << LG_PAGE) | (binind <<
    842 	    CHUNK_MAP_BININD_SHIFT) | flags | unzeroed | CHUNK_MAP_ALLOCATED);
    843 }
    844 
    845 JEMALLOC_ALWAYS_INLINE void
    846 arena_mapbits_unzeroed_set(arena_chunk_t *chunk, size_t pageind,
    847     size_t unzeroed)
    848 {
    849 	size_t *mapbitsp = arena_mapbitsp_get(chunk, pageind);
    850 	size_t mapbits = arena_mapbitsp_read(mapbitsp);
    851 
    852 	arena_mapbitsp_write(mapbitsp, (mapbits & ~CHUNK_MAP_UNZEROED) |
    853 	    unzeroed);
    854 }
    855 
    856 JEMALLOC_INLINE bool
    857 arena_prof_accum_impl(arena_t *arena, uint64_t accumbytes)
    858 {
    859 
    860 	cassert(config_prof);
    861 	assert(prof_interval != 0);
    862 
    863 	arena->prof_accumbytes += accumbytes;
    864 	if (arena->prof_accumbytes >= prof_interval) {
    865 		arena->prof_accumbytes -= prof_interval;
    866 		return (true);
    867 	}
    868 	return (false);
    869 }
    870 
    871 JEMALLOC_INLINE bool
    872 arena_prof_accum_locked(arena_t *arena, uint64_t accumbytes)
    873 {
    874 
    875 	cassert(config_prof);
    876 
    877 	if (prof_interval == 0)
    878 		return (false);
    879 	return (arena_prof_accum_impl(arena, accumbytes));
    880 }
    881 
    882 JEMALLOC_INLINE bool
    883 arena_prof_accum(arena_t *arena, uint64_t accumbytes)
    884 {
    885 
    886 	cassert(config_prof);
    887 
    888 	if (prof_interval == 0)
    889 		return (false);
    890 
    891 	{
    892 		bool ret;
    893 
    894 		malloc_mutex_lock(&arena->lock);
    895 		ret = arena_prof_accum_impl(arena, accumbytes);
    896 		malloc_mutex_unlock(&arena->lock);
    897 		return (ret);
    898 	}
    899 }
    900 
    901 JEMALLOC_ALWAYS_INLINE size_t
    902 arena_ptr_small_binind_get(const void *ptr, size_t mapbits)
    903 {
    904 	size_t binind;
    905 
    906 	binind = (mapbits & CHUNK_MAP_BININD_MASK) >> CHUNK_MAP_BININD_SHIFT;
    907 
    908 	if (config_debug) {
    909 		arena_chunk_t *chunk;
    910 		arena_t *arena;
    911 		size_t pageind;
    912 		size_t actual_mapbits;
    913 		arena_run_t *run;
    914 		arena_bin_t *bin;
    915 		size_t actual_binind;
    916 		arena_bin_info_t *bin_info;
    917 
    918 		assert(binind != BININD_INVALID);
    919 		assert(binind < NBINS);
    920 		chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
    921 		arena = chunk->arena;
    922 		pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
    923 		actual_mapbits = arena_mapbits_get(chunk, pageind);
    924 		assert(mapbits == actual_mapbits);
    925 		assert(arena_mapbits_large_get(chunk, pageind) == 0);
    926 		assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
    927 		run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind -
    928 		    (actual_mapbits >> LG_PAGE)) << LG_PAGE));
    929 		bin = run->bin;
    930 		actual_binind = bin - arena->bins;
    931 		assert(binind == actual_binind);
    932 		bin_info = &arena_bin_info[actual_binind];
    933 		assert(((uintptr_t)ptr - ((uintptr_t)run +
    934 		    (uintptr_t)bin_info->reg0_offset)) % bin_info->reg_interval
    935 		    == 0);
    936 	}
    937 
    938 	return (binind);
    939 }
    940 #  endif /* JEMALLOC_ARENA_INLINE_B */
    941 
    942 #  ifdef JEMALLOC_ARENA_INLINE_C
    943 JEMALLOC_INLINE size_t
    944 arena_bin_index(arena_t *arena, arena_bin_t *bin)
    945 {
    946 	size_t binind = bin - arena->bins;
    947 	assert(binind < NBINS);
    948 	return (binind);
    949 }
    950 
    951 JEMALLOC_INLINE unsigned
    952 arena_run_regind(arena_run_t *run, arena_bin_info_t *bin_info, const void *ptr)
    953 {
    954 	unsigned shift, diff, regind;
    955 	size_t interval;
    956 
    957 	/*
    958 	 * Freeing a pointer lower than region zero can cause assertion
    959 	 * failure.
    960 	 */
    961 	assert((uintptr_t)ptr >= (uintptr_t)run +
    962 	    (uintptr_t)bin_info->reg0_offset);
    963 
    964 	/*
    965 	 * Avoid doing division with a variable divisor if possible.  Using
    966 	 * actual division here can reduce allocator throughput by over 20%!
    967 	 */
    968 	diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run -
    969 	    bin_info->reg0_offset);
    970 
    971 	/* Rescale (factor powers of 2 out of the numerator and denominator). */
    972 	interval = bin_info->reg_interval;
    973 	shift = jemalloc_ffs(interval) - 1;
    974 	diff >>= shift;
    975 	interval >>= shift;
    976 
    977 	if (interval == 1) {
    978 		/* The divisor was a power of 2. */
    979 		regind = diff;
    980 	} else {
    981 		/*
    982 		 * To divide by a number D that is not a power of two we
    983 		 * multiply by (2^21 / D) and then right shift by 21 positions.
    984 		 *
    985 		 *   X / D
    986 		 *
    987 		 * becomes
    988 		 *
    989 		 *   (X * interval_invs[D - 3]) >> SIZE_INV_SHIFT
    990 		 *
    991 		 * We can omit the first three elements, because we never
    992 		 * divide by 0, and 1 and 2 are both powers of two, which are
    993 		 * handled above.
    994 		 */
    995 #define	SIZE_INV_SHIFT	((sizeof(unsigned) << 3) - LG_RUN_MAXREGS)
    996 #define	SIZE_INV(s)	(((1U << SIZE_INV_SHIFT) / (s)) + 1)
    997 		static const unsigned interval_invs[] = {
    998 		    SIZE_INV(3),
    999 		    SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7),
   1000 		    SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11),
   1001 		    SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15),
   1002 		    SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19),
   1003 		    SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23),
   1004 		    SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27),
   1005 		    SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31)
   1006 		};
   1007 
   1008 		if (interval <= ((sizeof(interval_invs) / sizeof(unsigned)) +
   1009 		    2)) {
   1010 			regind = (diff * interval_invs[interval - 3]) >>
   1011 			    SIZE_INV_SHIFT;
   1012 		} else
   1013 			regind = diff / interval;
   1014 #undef SIZE_INV
   1015 #undef SIZE_INV_SHIFT
   1016 	}
   1017 	assert(diff == regind * interval);
   1018 	assert(regind < bin_info->nregs);
   1019 
   1020 	return (regind);
   1021 }
   1022 
   1023 JEMALLOC_INLINE prof_ctx_t *
   1024 arena_prof_ctx_get(const void *ptr)
   1025 {
   1026 	prof_ctx_t *ret;
   1027 	arena_chunk_t *chunk;
   1028 	size_t pageind, mapbits;
   1029 
   1030 	cassert(config_prof);
   1031 	assert(ptr != NULL);
   1032 	assert(CHUNK_ADDR2BASE(ptr) != ptr);
   1033 
   1034 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   1035 	pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
   1036 	mapbits = arena_mapbits_get(chunk, pageind);
   1037 	assert((mapbits & CHUNK_MAP_ALLOCATED) != 0);
   1038 	if ((mapbits & CHUNK_MAP_LARGE) == 0)
   1039 		ret = (prof_ctx_t *)(uintptr_t)1U;
   1040 	else
   1041 		ret = arena_mapp_get(chunk, pageind)->prof_ctx;
   1042 
   1043 	return (ret);
   1044 }
   1045 
   1046 JEMALLOC_INLINE void
   1047 arena_prof_ctx_set(const void *ptr, prof_ctx_t *ctx)
   1048 {
   1049 	arena_chunk_t *chunk;
   1050 	size_t pageind;
   1051 
   1052 	cassert(config_prof);
   1053 	assert(ptr != NULL);
   1054 	assert(CHUNK_ADDR2BASE(ptr) != ptr);
   1055 
   1056 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   1057 	pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
   1058 	assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
   1059 
   1060 	if (arena_mapbits_large_get(chunk, pageind) != 0)
   1061 		arena_mapp_get(chunk, pageind)->prof_ctx = ctx;
   1062 }
   1063 
   1064 JEMALLOC_ALWAYS_INLINE void *
   1065 arena_malloc(arena_t *arena, size_t size, bool zero, bool try_tcache)
   1066 {
   1067 	tcache_t *tcache;
   1068 
   1069 	assert(size != 0);
   1070 	assert(size <= arena_maxclass);
   1071 
   1072 	if (size <= SMALL_MAXCLASS) {
   1073 		if (try_tcache && (tcache = tcache_get(true)) != NULL)
   1074 			return (tcache_alloc_small(tcache, size, zero));
   1075 		else {
   1076 			return (arena_malloc_small(choose_arena(arena), size,
   1077 			    zero));
   1078 		}
   1079 	} else {
   1080 		/*
   1081 		 * Initialize tcache after checking size in order to avoid
   1082 		 * infinite recursion during tcache initialization.
   1083 		 */
   1084 		if (try_tcache && size <= tcache_maxclass && (tcache =
   1085 		    tcache_get(true)) != NULL)
   1086 			return (tcache_alloc_large(tcache, size, zero));
   1087 		else {
   1088 			return (arena_malloc_large(choose_arena(arena), size,
   1089 			    zero));
   1090 		}
   1091 	}
   1092 }
   1093 
   1094 /* Return the size of the allocation pointed to by ptr. */
   1095 JEMALLOC_ALWAYS_INLINE size_t
   1096 arena_salloc(const void *ptr, bool demote)
   1097 {
   1098 	size_t ret;
   1099 	arena_chunk_t *chunk;
   1100 	size_t pageind, binind;
   1101 
   1102 	assert(ptr != NULL);
   1103 	assert(CHUNK_ADDR2BASE(ptr) != ptr);
   1104 
   1105 	chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr);
   1106 	pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
   1107 	assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
   1108 	binind = arena_mapbits_binind_get(chunk, pageind);
   1109 	if (binind == BININD_INVALID || (config_prof && demote == false &&
   1110 	    arena_mapbits_large_get(chunk, pageind) != 0)) {
   1111 		/*
   1112 		 * Large allocation.  In the common case (demote == true), and
   1113 		 * as this is an inline function, most callers will only end up
   1114 		 * looking at binind to determine that ptr is a small
   1115 		 * allocation.
   1116 		 */
   1117 		assert(((uintptr_t)ptr & PAGE_MASK) == 0);
   1118 		ret = arena_mapbits_large_size_get(chunk, pageind);
   1119 		assert(ret != 0);
   1120 		assert(pageind + (ret>>LG_PAGE) <= chunk_npages);
   1121 		assert(ret == PAGE || arena_mapbits_large_size_get(chunk,
   1122 		    pageind+(ret>>LG_PAGE)-1) == 0);
   1123 		assert(binind == arena_mapbits_binind_get(chunk,
   1124 		    pageind+(ret>>LG_PAGE)-1));
   1125 		assert(arena_mapbits_dirty_get(chunk, pageind) ==
   1126 		    arena_mapbits_dirty_get(chunk, pageind+(ret>>LG_PAGE)-1));
   1127 	} else {
   1128 		/* Small allocation (possibly promoted to a large object). */
   1129 		assert(arena_mapbits_large_get(chunk, pageind) != 0 ||
   1130 		    arena_ptr_small_binind_get(ptr, arena_mapbits_get(chunk,
   1131 		    pageind)) == binind);
   1132 		ret = small_bin2size(binind);
   1133 	}
   1134 
   1135 	return (ret);
   1136 }
   1137 
   1138 JEMALLOC_ALWAYS_INLINE void
   1139 arena_dalloc(arena_chunk_t *chunk, void *ptr, bool try_tcache)
   1140 {
   1141 	size_t pageind, mapbits;
   1142 	tcache_t *tcache;
   1143 
   1144 	assert(ptr != NULL);
   1145 	assert(CHUNK_ADDR2BASE(ptr) != ptr);
   1146 
   1147 	pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE;
   1148 	mapbits = arena_mapbits_get(chunk, pageind);
   1149 	assert(arena_mapbits_allocated_get(chunk, pageind) != 0);
   1150 	if ((mapbits & CHUNK_MAP_LARGE) == 0) {
   1151 		/* Small allocation. */
   1152 		if (try_tcache && (tcache = tcache_get(false)) != NULL) {
   1153 			size_t binind;
   1154 
   1155 			binind = arena_ptr_small_binind_get(ptr, mapbits);
   1156 			tcache_dalloc_small(tcache, ptr, binind);
   1157 		} else
   1158 			arena_dalloc_small(chunk->arena, chunk, ptr, pageind);
   1159 	} else {
   1160 		size_t size = arena_mapbits_large_size_get(chunk, pageind);
   1161 
   1162 		assert(((uintptr_t)ptr & PAGE_MASK) == 0);
   1163 
   1164 		if (try_tcache && size <= tcache_maxclass && (tcache =
   1165 		    tcache_get(false)) != NULL) {
   1166 			tcache_dalloc_large(tcache, ptr, size);
   1167 		} else
   1168 			arena_dalloc_large(chunk->arena, chunk, ptr);
   1169 	}
   1170 }
   1171 #  endif /* JEMALLOC_ARENA_INLINE_C */
   1172 #endif
   1173 
   1174 #endif /* JEMALLOC_H_INLINES */
   1175 /******************************************************************************/
   1176