1b7eaed25SJason Evans #ifndef JEMALLOC_INTERNAL_ARENA_INLINES_B_H
2b7eaed25SJason Evans #define JEMALLOC_INTERNAL_ARENA_INLINES_B_H
3b7eaed25SJason Evans 
4b7eaed25SJason Evans #include "jemalloc/internal/jemalloc_internal_types.h"
5b7eaed25SJason Evans #include "jemalloc/internal/mutex.h"
6b7eaed25SJason Evans #include "jemalloc/internal/rtree.h"
7c5ad8142SEric van Gyzen #include "jemalloc/internal/sc.h"
8b7eaed25SJason Evans #include "jemalloc/internal/sz.h"
9b7eaed25SJason Evans #include "jemalloc/internal/ticker.h"
10b7eaed25SJason Evans 
11c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE bool
arena_has_default_hooks(arena_t * arena)12c5ad8142SEric van Gyzen arena_has_default_hooks(arena_t *arena) {
13c5ad8142SEric van Gyzen 	return (extent_hooks_get(arena) == &extent_hooks_default);
14c5ad8142SEric van Gyzen }
15c5ad8142SEric van Gyzen 
16c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE arena_t *
arena_choose_maybe_huge(tsd_t * tsd,arena_t * arena,size_t size)17c5ad8142SEric van Gyzen arena_choose_maybe_huge(tsd_t *tsd, arena_t *arena, size_t size) {
18c5ad8142SEric van Gyzen 	if (arena != NULL) {
19c5ad8142SEric van Gyzen 		return arena;
20c5ad8142SEric van Gyzen 	}
21c5ad8142SEric van Gyzen 
22c5ad8142SEric van Gyzen 	/*
23c5ad8142SEric van Gyzen 	 * For huge allocations, use the dedicated huge arena if both are true:
24c5ad8142SEric van Gyzen 	 * 1) is using auto arena selection (i.e. arena == NULL), and 2) the
25c5ad8142SEric van Gyzen 	 * thread is not assigned to a manual arena.
26c5ad8142SEric van Gyzen 	 */
27c5ad8142SEric van Gyzen 	if (unlikely(size >= oversize_threshold)) {
28c5ad8142SEric van Gyzen 		arena_t *tsd_arena = tsd_arena_get(tsd);
29c5ad8142SEric van Gyzen 		if (tsd_arena == NULL || arena_is_auto(tsd_arena)) {
30c5ad8142SEric van Gyzen 			return arena_choose_huge(tsd);
31c5ad8142SEric van Gyzen 		}
32c5ad8142SEric van Gyzen 	}
33c5ad8142SEric van Gyzen 
34c5ad8142SEric van Gyzen 	return arena_choose(tsd, NULL);
35c5ad8142SEric van Gyzen }
36c5ad8142SEric van Gyzen 
37b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE prof_tctx_t *
arena_prof_tctx_get(tsdn_t * tsdn,const void * ptr,alloc_ctx_t * alloc_ctx)38b7eaed25SJason Evans arena_prof_tctx_get(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx) {
39b7eaed25SJason Evans 	cassert(config_prof);
40b7eaed25SJason Evans 	assert(ptr != NULL);
41b7eaed25SJason Evans 
42b7eaed25SJason Evans 	/* Static check. */
43b7eaed25SJason Evans 	if (alloc_ctx == NULL) {
44b7eaed25SJason Evans 		const extent_t *extent = iealloc(tsdn, ptr);
45b7eaed25SJason Evans 		if (unlikely(!extent_slab_get(extent))) {
46b7eaed25SJason Evans 			return large_prof_tctx_get(tsdn, extent);
47b7eaed25SJason Evans 		}
48b7eaed25SJason Evans 	} else {
49b7eaed25SJason Evans 		if (unlikely(!alloc_ctx->slab)) {
50b7eaed25SJason Evans 			return large_prof_tctx_get(tsdn, iealloc(tsdn, ptr));
51b7eaed25SJason Evans 		}
52b7eaed25SJason Evans 	}
53b7eaed25SJason Evans 	return (prof_tctx_t *)(uintptr_t)1U;
54b7eaed25SJason Evans }
55b7eaed25SJason Evans 
56b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_prof_tctx_set(tsdn_t * tsdn,const void * ptr,size_t usize,alloc_ctx_t * alloc_ctx,prof_tctx_t * tctx)57c5ad8142SEric van Gyzen arena_prof_tctx_set(tsdn_t *tsdn, const void *ptr, size_t usize,
58b7eaed25SJason Evans     alloc_ctx_t *alloc_ctx, prof_tctx_t *tctx) {
59b7eaed25SJason Evans 	cassert(config_prof);
60b7eaed25SJason Evans 	assert(ptr != NULL);
61b7eaed25SJason Evans 
62b7eaed25SJason Evans 	/* Static check. */
63b7eaed25SJason Evans 	if (alloc_ctx == NULL) {
64b7eaed25SJason Evans 		extent_t *extent = iealloc(tsdn, ptr);
65b7eaed25SJason Evans 		if (unlikely(!extent_slab_get(extent))) {
66b7eaed25SJason Evans 			large_prof_tctx_set(tsdn, extent, tctx);
67b7eaed25SJason Evans 		}
68b7eaed25SJason Evans 	} else {
69b7eaed25SJason Evans 		if (unlikely(!alloc_ctx->slab)) {
70b7eaed25SJason Evans 			large_prof_tctx_set(tsdn, iealloc(tsdn, ptr), tctx);
71b7eaed25SJason Evans 		}
72b7eaed25SJason Evans 	}
73b7eaed25SJason Evans }
74b7eaed25SJason Evans 
75b7eaed25SJason Evans static inline void
arena_prof_tctx_reset(tsdn_t * tsdn,const void * ptr,prof_tctx_t * tctx)76c5ad8142SEric van Gyzen arena_prof_tctx_reset(tsdn_t *tsdn, const void *ptr, prof_tctx_t *tctx) {
77b7eaed25SJason Evans 	cassert(config_prof);
78b7eaed25SJason Evans 	assert(ptr != NULL);
79b7eaed25SJason Evans 
80b7eaed25SJason Evans 	extent_t *extent = iealloc(tsdn, ptr);
81b7eaed25SJason Evans 	assert(!extent_slab_get(extent));
82b7eaed25SJason Evans 
83b7eaed25SJason Evans 	large_prof_tctx_reset(tsdn, extent);
84b7eaed25SJason Evans }
85b7eaed25SJason Evans 
86c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE nstime_t
arena_prof_alloc_time_get(tsdn_t * tsdn,const void * ptr,alloc_ctx_t * alloc_ctx)87c5ad8142SEric van Gyzen arena_prof_alloc_time_get(tsdn_t *tsdn, const void *ptr,
88c5ad8142SEric van Gyzen     alloc_ctx_t *alloc_ctx) {
89c5ad8142SEric van Gyzen 	cassert(config_prof);
90c5ad8142SEric van Gyzen 	assert(ptr != NULL);
91c5ad8142SEric van Gyzen 
92c5ad8142SEric van Gyzen 	extent_t *extent = iealloc(tsdn, ptr);
93c5ad8142SEric van Gyzen 	/*
94c5ad8142SEric van Gyzen 	 * Unlike arena_prof_prof_tctx_{get, set}, we only call this once we're
95c5ad8142SEric van Gyzen 	 * sure we have a sampled allocation.
96c5ad8142SEric van Gyzen 	 */
97c5ad8142SEric van Gyzen 	assert(!extent_slab_get(extent));
98c5ad8142SEric van Gyzen 	return large_prof_alloc_time_get(extent);
99c5ad8142SEric van Gyzen }
100c5ad8142SEric van Gyzen 
101c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE void
arena_prof_alloc_time_set(tsdn_t * tsdn,const void * ptr,alloc_ctx_t * alloc_ctx,nstime_t t)102c5ad8142SEric van Gyzen arena_prof_alloc_time_set(tsdn_t *tsdn, const void *ptr, alloc_ctx_t *alloc_ctx,
103c5ad8142SEric van Gyzen     nstime_t t) {
104c5ad8142SEric van Gyzen 	cassert(config_prof);
105c5ad8142SEric van Gyzen 	assert(ptr != NULL);
106c5ad8142SEric van Gyzen 
107c5ad8142SEric van Gyzen 	extent_t *extent = iealloc(tsdn, ptr);
108c5ad8142SEric van Gyzen 	assert(!extent_slab_get(extent));
109c5ad8142SEric van Gyzen 	large_prof_alloc_time_set(extent, t);
110c5ad8142SEric van Gyzen }
111c5ad8142SEric van Gyzen 
112b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_decay_ticks(tsdn_t * tsdn,arena_t * arena,unsigned nticks)113b7eaed25SJason Evans arena_decay_ticks(tsdn_t *tsdn, arena_t *arena, unsigned nticks) {
114b7eaed25SJason Evans 	tsd_t *tsd;
115b7eaed25SJason Evans 	ticker_t *decay_ticker;
116b7eaed25SJason Evans 
117b7eaed25SJason Evans 	if (unlikely(tsdn_null(tsdn))) {
118b7eaed25SJason Evans 		return;
119b7eaed25SJason Evans 	}
120b7eaed25SJason Evans 	tsd = tsdn_tsd(tsdn);
121b7eaed25SJason Evans 	decay_ticker = decay_ticker_get(tsd, arena_ind_get(arena));
122b7eaed25SJason Evans 	if (unlikely(decay_ticker == NULL)) {
123b7eaed25SJason Evans 		return;
124b7eaed25SJason Evans 	}
125b7eaed25SJason Evans 	if (unlikely(ticker_ticks(decay_ticker, nticks))) {
126b7eaed25SJason Evans 		arena_decay(tsdn, arena, false, false);
127b7eaed25SJason Evans 	}
128b7eaed25SJason Evans }
129b7eaed25SJason Evans 
130b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_decay_tick(tsdn_t * tsdn,arena_t * arena)131b7eaed25SJason Evans arena_decay_tick(tsdn_t *tsdn, arena_t *arena) {
132b7eaed25SJason Evans 	malloc_mutex_assert_not_owner(tsdn, &arena->decay_dirty.mtx);
133b7eaed25SJason Evans 	malloc_mutex_assert_not_owner(tsdn, &arena->decay_muzzy.mtx);
134b7eaed25SJason Evans 
135b7eaed25SJason Evans 	arena_decay_ticks(tsdn, arena, 1);
136b7eaed25SJason Evans }
137b7eaed25SJason Evans 
138c5ad8142SEric van Gyzen /* Purge a single extent to retained / unmapped directly. */
139c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE void
arena_decay_extent(tsdn_t * tsdn,arena_t * arena,extent_hooks_t ** r_extent_hooks,extent_t * extent)140c5ad8142SEric van Gyzen arena_decay_extent(tsdn_t *tsdn,arena_t *arena, extent_hooks_t **r_extent_hooks,
141c5ad8142SEric van Gyzen     extent_t *extent) {
142c5ad8142SEric van Gyzen 	size_t extent_size = extent_size_get(extent);
143c5ad8142SEric van Gyzen 	extent_dalloc_wrapper(tsdn, arena,
144c5ad8142SEric van Gyzen 	    r_extent_hooks, extent);
145c5ad8142SEric van Gyzen 	if (config_stats) {
146c5ad8142SEric van Gyzen 		/* Update stats accordingly. */
147c5ad8142SEric van Gyzen 		arena_stats_lock(tsdn, &arena->stats);
148c5ad8142SEric van Gyzen 		arena_stats_add_u64(tsdn, &arena->stats,
149c5ad8142SEric van Gyzen 		    &arena->decay_dirty.stats->nmadvise, 1);
150c5ad8142SEric van Gyzen 		arena_stats_add_u64(tsdn, &arena->stats,
151c5ad8142SEric van Gyzen 		    &arena->decay_dirty.stats->purged, extent_size >> LG_PAGE);
152c5ad8142SEric van Gyzen 		arena_stats_sub_zu(tsdn, &arena->stats, &arena->stats.mapped,
153c5ad8142SEric van Gyzen 		    extent_size);
154c5ad8142SEric van Gyzen 		arena_stats_unlock(tsdn, &arena->stats);
155c5ad8142SEric van Gyzen 	}
156c5ad8142SEric van Gyzen }
157c5ad8142SEric van Gyzen 
158b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void *
arena_malloc(tsdn_t * tsdn,arena_t * arena,size_t size,szind_t ind,bool zero,tcache_t * tcache,bool slow_path)159b7eaed25SJason Evans arena_malloc(tsdn_t *tsdn, arena_t *arena, size_t size, szind_t ind, bool zero,
160b7eaed25SJason Evans     tcache_t *tcache, bool slow_path) {
161b7eaed25SJason Evans 	assert(!tsdn_null(tsdn) || tcache == NULL);
162b7eaed25SJason Evans 
163b7eaed25SJason Evans 	if (likely(tcache != NULL)) {
164c5ad8142SEric van Gyzen 		if (likely(size <= SC_SMALL_MAXCLASS)) {
165b7eaed25SJason Evans 			return tcache_alloc_small(tsdn_tsd(tsdn), arena,
166b7eaed25SJason Evans 			    tcache, size, ind, zero, slow_path);
167b7eaed25SJason Evans 		}
168b7eaed25SJason Evans 		if (likely(size <= tcache_maxclass)) {
169b7eaed25SJason Evans 			return tcache_alloc_large(tsdn_tsd(tsdn), arena,
170b7eaed25SJason Evans 			    tcache, size, ind, zero, slow_path);
171b7eaed25SJason Evans 		}
172b7eaed25SJason Evans 		/* (size > tcache_maxclass) case falls through. */
173b7eaed25SJason Evans 		assert(size > tcache_maxclass);
174b7eaed25SJason Evans 	}
175b7eaed25SJason Evans 
176b7eaed25SJason Evans 	return arena_malloc_hard(tsdn, arena, size, ind, zero);
177b7eaed25SJason Evans }
178b7eaed25SJason Evans 
179b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE arena_t *
arena_aalloc(tsdn_t * tsdn,const void * ptr)180b7eaed25SJason Evans arena_aalloc(tsdn_t *tsdn, const void *ptr) {
181b7eaed25SJason Evans 	return extent_arena_get(iealloc(tsdn, ptr));
182b7eaed25SJason Evans }
183b7eaed25SJason Evans 
184b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE size_t
arena_salloc(tsdn_t * tsdn,const void * ptr)185b7eaed25SJason Evans arena_salloc(tsdn_t *tsdn, const void *ptr) {
186b7eaed25SJason Evans 	assert(ptr != NULL);
187b7eaed25SJason Evans 
188b7eaed25SJason Evans 	rtree_ctx_t rtree_ctx_fallback;
189b7eaed25SJason Evans 	rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
190b7eaed25SJason Evans 
191b7eaed25SJason Evans 	szind_t szind = rtree_szind_read(tsdn, &extents_rtree, rtree_ctx,
192b7eaed25SJason Evans 	    (uintptr_t)ptr, true);
193c5ad8142SEric van Gyzen 	assert(szind != SC_NSIZES);
194b7eaed25SJason Evans 
195b7eaed25SJason Evans 	return sz_index2size(szind);
196b7eaed25SJason Evans }
197b7eaed25SJason Evans 
198b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE size_t
arena_vsalloc(tsdn_t * tsdn,const void * ptr)199b7eaed25SJason Evans arena_vsalloc(tsdn_t *tsdn, const void *ptr) {
200b7eaed25SJason Evans 	/*
201b7eaed25SJason Evans 	 * Return 0 if ptr is not within an extent managed by jemalloc.  This
202b7eaed25SJason Evans 	 * function has two extra costs relative to isalloc():
203b7eaed25SJason Evans 	 * - The rtree calls cannot claim to be dependent lookups, which induces
204b7eaed25SJason Evans 	 *   rtree lookup load dependencies.
205b7eaed25SJason Evans 	 * - The lookup may fail, so there is an extra branch to check for
206b7eaed25SJason Evans 	 *   failure.
207b7eaed25SJason Evans 	 */
208b7eaed25SJason Evans 
209b7eaed25SJason Evans 	rtree_ctx_t rtree_ctx_fallback;
210b7eaed25SJason Evans 	rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
211b7eaed25SJason Evans 
212b7eaed25SJason Evans 	extent_t *extent;
213b7eaed25SJason Evans 	szind_t szind;
214b7eaed25SJason Evans 	if (rtree_extent_szind_read(tsdn, &extents_rtree, rtree_ctx,
215b7eaed25SJason Evans 	    (uintptr_t)ptr, false, &extent, &szind)) {
216b7eaed25SJason Evans 		return 0;
217b7eaed25SJason Evans 	}
218b7eaed25SJason Evans 
219b7eaed25SJason Evans 	if (extent == NULL) {
220b7eaed25SJason Evans 		return 0;
221b7eaed25SJason Evans 	}
222b7eaed25SJason Evans 	assert(extent_state_get(extent) == extent_state_active);
223b7eaed25SJason Evans 	/* Only slab members should be looked up via interior pointers. */
224b7eaed25SJason Evans 	assert(extent_addr_get(extent) == ptr || extent_slab_get(extent));
225b7eaed25SJason Evans 
226c5ad8142SEric van Gyzen 	assert(szind != SC_NSIZES);
227b7eaed25SJason Evans 
228b7eaed25SJason Evans 	return sz_index2size(szind);
229b7eaed25SJason Evans }
230b7eaed25SJason Evans 
231b7eaed25SJason Evans static inline void
arena_dalloc_large_no_tcache(tsdn_t * tsdn,void * ptr,szind_t szind)232c5ad8142SEric van Gyzen arena_dalloc_large_no_tcache(tsdn_t *tsdn, void *ptr, szind_t szind) {
233c5ad8142SEric van Gyzen 	if (config_prof && unlikely(szind < SC_NBINS)) {
234c5ad8142SEric van Gyzen 		arena_dalloc_promoted(tsdn, ptr, NULL, true);
235c5ad8142SEric van Gyzen 	} else {
236c5ad8142SEric van Gyzen 		extent_t *extent = iealloc(tsdn, ptr);
237c5ad8142SEric van Gyzen 		large_dalloc(tsdn, extent);
238c5ad8142SEric van Gyzen 	}
239c5ad8142SEric van Gyzen }
240c5ad8142SEric van Gyzen 
241c5ad8142SEric van Gyzen static inline void
arena_dalloc_no_tcache(tsdn_t * tsdn,void * ptr)242b7eaed25SJason Evans arena_dalloc_no_tcache(tsdn_t *tsdn, void *ptr) {
243b7eaed25SJason Evans 	assert(ptr != NULL);
244b7eaed25SJason Evans 
245b7eaed25SJason Evans 	rtree_ctx_t rtree_ctx_fallback;
246b7eaed25SJason Evans 	rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn, &rtree_ctx_fallback);
247b7eaed25SJason Evans 
248b7eaed25SJason Evans 	szind_t szind;
249b7eaed25SJason Evans 	bool slab;
250b7eaed25SJason Evans 	rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx, (uintptr_t)ptr,
251b7eaed25SJason Evans 	    true, &szind, &slab);
252b7eaed25SJason Evans 
253b7eaed25SJason Evans 	if (config_debug) {
254b7eaed25SJason Evans 		extent_t *extent = rtree_extent_read(tsdn, &extents_rtree,
255b7eaed25SJason Evans 		    rtree_ctx, (uintptr_t)ptr, true);
256b7eaed25SJason Evans 		assert(szind == extent_szind_get(extent));
257c5ad8142SEric van Gyzen 		assert(szind < SC_NSIZES);
258b7eaed25SJason Evans 		assert(slab == extent_slab_get(extent));
259b7eaed25SJason Evans 	}
260b7eaed25SJason Evans 
261b7eaed25SJason Evans 	if (likely(slab)) {
262b7eaed25SJason Evans 		/* Small allocation. */
263b7eaed25SJason Evans 		arena_dalloc_small(tsdn, ptr);
264b7eaed25SJason Evans 	} else {
265c5ad8142SEric van Gyzen 		arena_dalloc_large_no_tcache(tsdn, ptr, szind);
266c5ad8142SEric van Gyzen 	}
267c5ad8142SEric van Gyzen }
268c5ad8142SEric van Gyzen 
269c5ad8142SEric van Gyzen JEMALLOC_ALWAYS_INLINE void
arena_dalloc_large(tsdn_t * tsdn,void * ptr,tcache_t * tcache,szind_t szind,bool slow_path)270c5ad8142SEric van Gyzen arena_dalloc_large(tsdn_t *tsdn, void *ptr, tcache_t *tcache, szind_t szind,
271c5ad8142SEric van Gyzen     bool slow_path) {
272c5ad8142SEric van Gyzen 	if (szind < nhbins) {
273c5ad8142SEric van Gyzen 		if (config_prof && unlikely(szind < SC_NBINS)) {
274c5ad8142SEric van Gyzen 			arena_dalloc_promoted(tsdn, ptr, tcache, slow_path);
275c5ad8142SEric van Gyzen 		} else {
276c5ad8142SEric van Gyzen 			tcache_dalloc_large(tsdn_tsd(tsdn), tcache, ptr, szind,
277c5ad8142SEric van Gyzen 			    slow_path);
278c5ad8142SEric van Gyzen 		}
279c5ad8142SEric van Gyzen 	} else {
280b7eaed25SJason Evans 		extent_t *extent = iealloc(tsdn, ptr);
281b7eaed25SJason Evans 		large_dalloc(tsdn, extent);
282b7eaed25SJason Evans 	}
283b7eaed25SJason Evans }
284b7eaed25SJason Evans 
285b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_dalloc(tsdn_t * tsdn,void * ptr,tcache_t * tcache,alloc_ctx_t * alloc_ctx,bool slow_path)286b7eaed25SJason Evans arena_dalloc(tsdn_t *tsdn, void *ptr, tcache_t *tcache,
287b7eaed25SJason Evans     alloc_ctx_t *alloc_ctx, bool slow_path) {
288b7eaed25SJason Evans 	assert(!tsdn_null(tsdn) || tcache == NULL);
289b7eaed25SJason Evans 	assert(ptr != NULL);
290b7eaed25SJason Evans 
291b7eaed25SJason Evans 	if (unlikely(tcache == NULL)) {
292b7eaed25SJason Evans 		arena_dalloc_no_tcache(tsdn, ptr);
293b7eaed25SJason Evans 		return;
294b7eaed25SJason Evans 	}
295b7eaed25SJason Evans 
296b7eaed25SJason Evans 	szind_t szind;
297b7eaed25SJason Evans 	bool slab;
298b7eaed25SJason Evans 	rtree_ctx_t *rtree_ctx;
299b7eaed25SJason Evans 	if (alloc_ctx != NULL) {
300b7eaed25SJason Evans 		szind = alloc_ctx->szind;
301b7eaed25SJason Evans 		slab = alloc_ctx->slab;
302c5ad8142SEric van Gyzen 		assert(szind != SC_NSIZES);
303b7eaed25SJason Evans 	} else {
304b7eaed25SJason Evans 		rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn));
305b7eaed25SJason Evans 		rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
306b7eaed25SJason Evans 		    (uintptr_t)ptr, true, &szind, &slab);
307b7eaed25SJason Evans 	}
308b7eaed25SJason Evans 
309b7eaed25SJason Evans 	if (config_debug) {
310b7eaed25SJason Evans 		rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn));
311b7eaed25SJason Evans 		extent_t *extent = rtree_extent_read(tsdn, &extents_rtree,
312b7eaed25SJason Evans 		    rtree_ctx, (uintptr_t)ptr, true);
313b7eaed25SJason Evans 		assert(szind == extent_szind_get(extent));
314c5ad8142SEric van Gyzen 		assert(szind < SC_NSIZES);
315b7eaed25SJason Evans 		assert(slab == extent_slab_get(extent));
316b7eaed25SJason Evans 	}
317b7eaed25SJason Evans 
318b7eaed25SJason Evans 	if (likely(slab)) {
319b7eaed25SJason Evans 		/* Small allocation. */
320b7eaed25SJason Evans 		tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, szind,
321b7eaed25SJason Evans 		    slow_path);
322b7eaed25SJason Evans 	} else {
323c5ad8142SEric van Gyzen 		arena_dalloc_large(tsdn, ptr, tcache, szind, slow_path);
324b7eaed25SJason Evans 	}
325b7eaed25SJason Evans }
326b7eaed25SJason Evans 
327b7eaed25SJason Evans static inline void
arena_sdalloc_no_tcache(tsdn_t * tsdn,void * ptr,size_t size)328b7eaed25SJason Evans arena_sdalloc_no_tcache(tsdn_t *tsdn, void *ptr, size_t size) {
329b7eaed25SJason Evans 	assert(ptr != NULL);
330c5ad8142SEric van Gyzen 	assert(size <= SC_LARGE_MAXCLASS);
331b7eaed25SJason Evans 
332b7eaed25SJason Evans 	szind_t szind;
333b7eaed25SJason Evans 	bool slab;
334b7eaed25SJason Evans 	if (!config_prof || !opt_prof) {
335b7eaed25SJason Evans 		/*
336b7eaed25SJason Evans 		 * There is no risk of being confused by a promoted sampled
337b7eaed25SJason Evans 		 * object, so base szind and slab on the given size.
338b7eaed25SJason Evans 		 */
339b7eaed25SJason Evans 		szind = sz_size2index(size);
340c5ad8142SEric van Gyzen 		slab = (szind < SC_NBINS);
341b7eaed25SJason Evans 	}
342b7eaed25SJason Evans 
343b7eaed25SJason Evans 	if ((config_prof && opt_prof) || config_debug) {
344b7eaed25SJason Evans 		rtree_ctx_t rtree_ctx_fallback;
345b7eaed25SJason Evans 		rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn,
346b7eaed25SJason Evans 		    &rtree_ctx_fallback);
347b7eaed25SJason Evans 
348b7eaed25SJason Evans 		rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
349b7eaed25SJason Evans 		    (uintptr_t)ptr, true, &szind, &slab);
350b7eaed25SJason Evans 
351b7eaed25SJason Evans 		assert(szind == sz_size2index(size));
352c5ad8142SEric van Gyzen 		assert((config_prof && opt_prof) || slab == (szind < SC_NBINS));
353b7eaed25SJason Evans 
354b7eaed25SJason Evans 		if (config_debug) {
355b7eaed25SJason Evans 			extent_t *extent = rtree_extent_read(tsdn,
356b7eaed25SJason Evans 			    &extents_rtree, rtree_ctx, (uintptr_t)ptr, true);
357b7eaed25SJason Evans 			assert(szind == extent_szind_get(extent));
358b7eaed25SJason Evans 			assert(slab == extent_slab_get(extent));
359b7eaed25SJason Evans 		}
360b7eaed25SJason Evans 	}
361b7eaed25SJason Evans 
362b7eaed25SJason Evans 	if (likely(slab)) {
363b7eaed25SJason Evans 		/* Small allocation. */
364b7eaed25SJason Evans 		arena_dalloc_small(tsdn, ptr);
365b7eaed25SJason Evans 	} else {
366c5ad8142SEric van Gyzen 		arena_dalloc_large_no_tcache(tsdn, ptr, szind);
367b7eaed25SJason Evans 	}
368b7eaed25SJason Evans }
369b7eaed25SJason Evans 
370b7eaed25SJason Evans JEMALLOC_ALWAYS_INLINE void
arena_sdalloc(tsdn_t * tsdn,void * ptr,size_t size,tcache_t * tcache,alloc_ctx_t * alloc_ctx,bool slow_path)371b7eaed25SJason Evans arena_sdalloc(tsdn_t *tsdn, void *ptr, size_t size, tcache_t *tcache,
372b7eaed25SJason Evans     alloc_ctx_t *alloc_ctx, bool slow_path) {
373b7eaed25SJason Evans 	assert(!tsdn_null(tsdn) || tcache == NULL);
374b7eaed25SJason Evans 	assert(ptr != NULL);
375c5ad8142SEric van Gyzen 	assert(size <= SC_LARGE_MAXCLASS);
376b7eaed25SJason Evans 
377b7eaed25SJason Evans 	if (unlikely(tcache == NULL)) {
378b7eaed25SJason Evans 		arena_sdalloc_no_tcache(tsdn, ptr, size);
379b7eaed25SJason Evans 		return;
380b7eaed25SJason Evans 	}
381b7eaed25SJason Evans 
382b7eaed25SJason Evans 	szind_t szind;
383b7eaed25SJason Evans 	bool slab;
384c5ad8142SEric van Gyzen 	alloc_ctx_t local_ctx;
385b7eaed25SJason Evans 	if (config_prof && opt_prof) {
386b7eaed25SJason Evans 		if (alloc_ctx == NULL) {
387b7eaed25SJason Evans 			/* Uncommon case and should be a static check. */
388b7eaed25SJason Evans 			rtree_ctx_t rtree_ctx_fallback;
389b7eaed25SJason Evans 			rtree_ctx_t *rtree_ctx = tsdn_rtree_ctx(tsdn,
390b7eaed25SJason Evans 			    &rtree_ctx_fallback);
391b7eaed25SJason Evans 			rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
392b7eaed25SJason Evans 			    (uintptr_t)ptr, true, &local_ctx.szind,
393b7eaed25SJason Evans 			    &local_ctx.slab);
394b7eaed25SJason Evans 			assert(local_ctx.szind == sz_size2index(size));
395b7eaed25SJason Evans 			alloc_ctx = &local_ctx;
396b7eaed25SJason Evans 		}
397b7eaed25SJason Evans 		slab = alloc_ctx->slab;
398b7eaed25SJason Evans 		szind = alloc_ctx->szind;
399b7eaed25SJason Evans 	} else {
400b7eaed25SJason Evans 		/*
401b7eaed25SJason Evans 		 * There is no risk of being confused by a promoted sampled
402b7eaed25SJason Evans 		 * object, so base szind and slab on the given size.
403b7eaed25SJason Evans 		 */
404b7eaed25SJason Evans 		szind = sz_size2index(size);
405c5ad8142SEric van Gyzen 		slab = (szind < SC_NBINS);
406b7eaed25SJason Evans 	}
407b7eaed25SJason Evans 
408b7eaed25SJason Evans 	if (config_debug) {
409b7eaed25SJason Evans 		rtree_ctx_t *rtree_ctx = tsd_rtree_ctx(tsdn_tsd(tsdn));
410b7eaed25SJason Evans 		rtree_szind_slab_read(tsdn, &extents_rtree, rtree_ctx,
411b7eaed25SJason Evans 		    (uintptr_t)ptr, true, &szind, &slab);
412b7eaed25SJason Evans 		extent_t *extent = rtree_extent_read(tsdn,
413b7eaed25SJason Evans 		    &extents_rtree, rtree_ctx, (uintptr_t)ptr, true);
414b7eaed25SJason Evans 		assert(szind == extent_szind_get(extent));
415b7eaed25SJason Evans 		assert(slab == extent_slab_get(extent));
416b7eaed25SJason Evans 	}
417b7eaed25SJason Evans 
418b7eaed25SJason Evans 	if (likely(slab)) {
419b7eaed25SJason Evans 		/* Small allocation. */
420b7eaed25SJason Evans 		tcache_dalloc_small(tsdn_tsd(tsdn), tcache, ptr, szind,
421b7eaed25SJason Evans 		    slow_path);
422b7eaed25SJason Evans 	} else {
423c5ad8142SEric van Gyzen 		arena_dalloc_large(tsdn, ptr, tcache, szind, slow_path);
424b7eaed25SJason Evans 	}
425b7eaed25SJason Evans }
426b7eaed25SJason Evans 
427b7eaed25SJason Evans #endif /* JEMALLOC_INTERNAL_ARENA_INLINES_B_H */
428