xref: /aosp_15_r20/external/jemalloc_new/include/jemalloc/internal/sz.h (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_INTERNAL_SIZE_H
2*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_INTERNAL_SIZE_H
3*1208bc7eSAndroid Build Coastguard Worker 
4*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/bit_util.h"
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/pages.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/size_classes.h"
7*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/util.h"
8*1208bc7eSAndroid Build Coastguard Worker 
9*1208bc7eSAndroid Build Coastguard Worker /*
10*1208bc7eSAndroid Build Coastguard Worker  * sz module: Size computations.
11*1208bc7eSAndroid Build Coastguard Worker  *
12*1208bc7eSAndroid Build Coastguard Worker  * Some abbreviations used here:
13*1208bc7eSAndroid Build Coastguard Worker  *   p: Page
14*1208bc7eSAndroid Build Coastguard Worker  *   ind: Index
15*1208bc7eSAndroid Build Coastguard Worker  *   s, sz: Size
16*1208bc7eSAndroid Build Coastguard Worker  *   u: Usable size
17*1208bc7eSAndroid Build Coastguard Worker  *   a: Aligned
18*1208bc7eSAndroid Build Coastguard Worker  *
19*1208bc7eSAndroid Build Coastguard Worker  * These are not always used completely consistently, but should be enough to
20*1208bc7eSAndroid Build Coastguard Worker  * interpret function names.  E.g. sz_psz2ind converts page size to page size
21*1208bc7eSAndroid Build Coastguard Worker  * index; sz_sa2u converts a (size, alignment) allocation request to the usable
22*1208bc7eSAndroid Build Coastguard Worker  * size that would result from such an allocation.
23*1208bc7eSAndroid Build Coastguard Worker  */
24*1208bc7eSAndroid Build Coastguard Worker 
25*1208bc7eSAndroid Build Coastguard Worker /*
26*1208bc7eSAndroid Build Coastguard Worker  * sz_pind2sz_tab encodes the same information as could be computed by
27*1208bc7eSAndroid Build Coastguard Worker  * sz_pind2sz_compute().
28*1208bc7eSAndroid Build Coastguard Worker  */
29*1208bc7eSAndroid Build Coastguard Worker extern size_t const sz_pind2sz_tab[NPSIZES+1];
30*1208bc7eSAndroid Build Coastguard Worker /*
31*1208bc7eSAndroid Build Coastguard Worker  * sz_index2size_tab encodes the same information as could be computed (at
32*1208bc7eSAndroid Build Coastguard Worker  * unacceptable cost in some code paths) by sz_index2size_compute().
33*1208bc7eSAndroid Build Coastguard Worker  */
34*1208bc7eSAndroid Build Coastguard Worker extern size_t const sz_index2size_tab[NSIZES];
35*1208bc7eSAndroid Build Coastguard Worker /*
36*1208bc7eSAndroid Build Coastguard Worker  * sz_size2index_tab is a compact lookup table that rounds request sizes up to
37*1208bc7eSAndroid Build Coastguard Worker  * size classes.  In order to reduce cache footprint, the table is compressed,
38*1208bc7eSAndroid Build Coastguard Worker  * and all accesses are via sz_size2index().
39*1208bc7eSAndroid Build Coastguard Worker  */
40*1208bc7eSAndroid Build Coastguard Worker extern uint8_t const sz_size2index_tab[];
41*1208bc7eSAndroid Build Coastguard Worker 
42*1208bc7eSAndroid Build Coastguard Worker static const size_t sz_large_pad =
43*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_CACHE_OBLIVIOUS
44*1208bc7eSAndroid Build Coastguard Worker     PAGE
45*1208bc7eSAndroid Build Coastguard Worker #else
46*1208bc7eSAndroid Build Coastguard Worker     0
47*1208bc7eSAndroid Build Coastguard Worker #endif
48*1208bc7eSAndroid Build Coastguard Worker     ;
49*1208bc7eSAndroid Build Coastguard Worker 
50*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE pszind_t
sz_psz2ind(size_t psz)51*1208bc7eSAndroid Build Coastguard Worker sz_psz2ind(size_t psz) {
52*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(psz > LARGE_MAXCLASS)) {
53*1208bc7eSAndroid Build Coastguard Worker 		return NPSIZES;
54*1208bc7eSAndroid Build Coastguard Worker 	}
55*1208bc7eSAndroid Build Coastguard Worker 	{
56*1208bc7eSAndroid Build Coastguard Worker 		pszind_t x = lg_floor((psz<<1)-1);
57*1208bc7eSAndroid Build Coastguard Worker 		pszind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_PAGE) ? 0 : x -
58*1208bc7eSAndroid Build Coastguard Worker 		    (LG_SIZE_CLASS_GROUP + LG_PAGE);
59*1208bc7eSAndroid Build Coastguard Worker 		pszind_t grp = shift << LG_SIZE_CLASS_GROUP;
60*1208bc7eSAndroid Build Coastguard Worker 
61*1208bc7eSAndroid Build Coastguard Worker 		pszind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
62*1208bc7eSAndroid Build Coastguard Worker 		    LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
63*1208bc7eSAndroid Build Coastguard Worker 
64*1208bc7eSAndroid Build Coastguard Worker 		size_t delta_inverse_mask = ZU(-1) << lg_delta;
65*1208bc7eSAndroid Build Coastguard Worker 		pszind_t mod = ((((psz-1) & delta_inverse_mask) >> lg_delta)) &
66*1208bc7eSAndroid Build Coastguard Worker 		    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
67*1208bc7eSAndroid Build Coastguard Worker 
68*1208bc7eSAndroid Build Coastguard Worker 		pszind_t ind = grp + mod;
69*1208bc7eSAndroid Build Coastguard Worker 		return ind;
70*1208bc7eSAndroid Build Coastguard Worker 	}
71*1208bc7eSAndroid Build Coastguard Worker }
72*1208bc7eSAndroid Build Coastguard Worker 
73*1208bc7eSAndroid Build Coastguard Worker static inline size_t
sz_pind2sz_compute(pszind_t pind)74*1208bc7eSAndroid Build Coastguard Worker sz_pind2sz_compute(pszind_t pind) {
75*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(pind == NPSIZES)) {
76*1208bc7eSAndroid Build Coastguard Worker 		return LARGE_MAXCLASS + PAGE;
77*1208bc7eSAndroid Build Coastguard Worker 	}
78*1208bc7eSAndroid Build Coastguard Worker 	{
79*1208bc7eSAndroid Build Coastguard Worker 		size_t grp = pind >> LG_SIZE_CLASS_GROUP;
80*1208bc7eSAndroid Build Coastguard Worker 		size_t mod = pind & ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
81*1208bc7eSAndroid Build Coastguard Worker 
82*1208bc7eSAndroid Build Coastguard Worker 		size_t grp_size_mask = ~((!!grp)-1);
83*1208bc7eSAndroid Build Coastguard Worker 		size_t grp_size = ((ZU(1) << (LG_PAGE +
84*1208bc7eSAndroid Build Coastguard Worker 		    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;
85*1208bc7eSAndroid Build Coastguard Worker 
86*1208bc7eSAndroid Build Coastguard Worker 		size_t shift = (grp == 0) ? 1 : grp;
87*1208bc7eSAndroid Build Coastguard Worker 		size_t lg_delta = shift + (LG_PAGE-1);
88*1208bc7eSAndroid Build Coastguard Worker 		size_t mod_size = (mod+1) << lg_delta;
89*1208bc7eSAndroid Build Coastguard Worker 
90*1208bc7eSAndroid Build Coastguard Worker 		size_t sz = grp_size + mod_size;
91*1208bc7eSAndroid Build Coastguard Worker 		return sz;
92*1208bc7eSAndroid Build Coastguard Worker 	}
93*1208bc7eSAndroid Build Coastguard Worker }
94*1208bc7eSAndroid Build Coastguard Worker 
95*1208bc7eSAndroid Build Coastguard Worker static inline size_t
sz_pind2sz_lookup(pszind_t pind)96*1208bc7eSAndroid Build Coastguard Worker sz_pind2sz_lookup(pszind_t pind) {
97*1208bc7eSAndroid Build Coastguard Worker 	size_t ret = (size_t)sz_pind2sz_tab[pind];
98*1208bc7eSAndroid Build Coastguard Worker 	assert(ret == sz_pind2sz_compute(pind));
99*1208bc7eSAndroid Build Coastguard Worker 	return ret;
100*1208bc7eSAndroid Build Coastguard Worker }
101*1208bc7eSAndroid Build Coastguard Worker 
102*1208bc7eSAndroid Build Coastguard Worker static inline size_t
sz_pind2sz(pszind_t pind)103*1208bc7eSAndroid Build Coastguard Worker sz_pind2sz(pszind_t pind) {
104*1208bc7eSAndroid Build Coastguard Worker 	assert(pind < NPSIZES+1);
105*1208bc7eSAndroid Build Coastguard Worker 	return sz_pind2sz_lookup(pind);
106*1208bc7eSAndroid Build Coastguard Worker }
107*1208bc7eSAndroid Build Coastguard Worker 
108*1208bc7eSAndroid Build Coastguard Worker static inline size_t
sz_psz2u(size_t psz)109*1208bc7eSAndroid Build Coastguard Worker sz_psz2u(size_t psz) {
110*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(psz > LARGE_MAXCLASS)) {
111*1208bc7eSAndroid Build Coastguard Worker 		return LARGE_MAXCLASS + PAGE;
112*1208bc7eSAndroid Build Coastguard Worker 	}
113*1208bc7eSAndroid Build Coastguard Worker 	{
114*1208bc7eSAndroid Build Coastguard Worker 		size_t x = lg_floor((psz<<1)-1);
115*1208bc7eSAndroid Build Coastguard Worker 		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_PAGE + 1) ?
116*1208bc7eSAndroid Build Coastguard Worker 		    LG_PAGE : x - LG_SIZE_CLASS_GROUP - 1;
117*1208bc7eSAndroid Build Coastguard Worker 		size_t delta = ZU(1) << lg_delta;
118*1208bc7eSAndroid Build Coastguard Worker 		size_t delta_mask = delta - 1;
119*1208bc7eSAndroid Build Coastguard Worker 		size_t usize = (psz + delta_mask) & ~delta_mask;
120*1208bc7eSAndroid Build Coastguard Worker 		return usize;
121*1208bc7eSAndroid Build Coastguard Worker 	}
122*1208bc7eSAndroid Build Coastguard Worker }
123*1208bc7eSAndroid Build Coastguard Worker 
124*1208bc7eSAndroid Build Coastguard Worker static inline szind_t
sz_size2index_compute(size_t size)125*1208bc7eSAndroid Build Coastguard Worker sz_size2index_compute(size_t size) {
126*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(size > LARGE_MAXCLASS)) {
127*1208bc7eSAndroid Build Coastguard Worker 		return NSIZES;
128*1208bc7eSAndroid Build Coastguard Worker 	}
129*1208bc7eSAndroid Build Coastguard Worker #if (NTBINS != 0)
130*1208bc7eSAndroid Build Coastguard Worker 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
131*1208bc7eSAndroid Build Coastguard Worker 		szind_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
132*1208bc7eSAndroid Build Coastguard Worker 		szind_t lg_ceil = lg_floor(pow2_ceil_zu(size));
133*1208bc7eSAndroid Build Coastguard Worker 		return (lg_ceil < lg_tmin ? 0 : lg_ceil - lg_tmin);
134*1208bc7eSAndroid Build Coastguard Worker 	}
135*1208bc7eSAndroid Build Coastguard Worker #endif
136*1208bc7eSAndroid Build Coastguard Worker 	{
137*1208bc7eSAndroid Build Coastguard Worker 		szind_t x = lg_floor((size<<1)-1);
138*1208bc7eSAndroid Build Coastguard Worker 		szind_t shift = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM) ? 0 :
139*1208bc7eSAndroid Build Coastguard Worker 		    x - (LG_SIZE_CLASS_GROUP + LG_QUANTUM);
140*1208bc7eSAndroid Build Coastguard Worker 		szind_t grp = shift << LG_SIZE_CLASS_GROUP;
141*1208bc7eSAndroid Build Coastguard Worker 
142*1208bc7eSAndroid Build Coastguard Worker 		szind_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
143*1208bc7eSAndroid Build Coastguard Worker 		    ? LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
144*1208bc7eSAndroid Build Coastguard Worker 
145*1208bc7eSAndroid Build Coastguard Worker 		size_t delta_inverse_mask = ZU(-1) << lg_delta;
146*1208bc7eSAndroid Build Coastguard Worker 		szind_t mod = ((((size-1) & delta_inverse_mask) >> lg_delta)) &
147*1208bc7eSAndroid Build Coastguard Worker 		    ((ZU(1) << LG_SIZE_CLASS_GROUP) - 1);
148*1208bc7eSAndroid Build Coastguard Worker 
149*1208bc7eSAndroid Build Coastguard Worker 		szind_t index = NTBINS + grp + mod;
150*1208bc7eSAndroid Build Coastguard Worker 		return index;
151*1208bc7eSAndroid Build Coastguard Worker 	}
152*1208bc7eSAndroid Build Coastguard Worker }
153*1208bc7eSAndroid Build Coastguard Worker 
154*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE szind_t
sz_size2index_lookup(size_t size)155*1208bc7eSAndroid Build Coastguard Worker sz_size2index_lookup(size_t size) {
156*1208bc7eSAndroid Build Coastguard Worker 	assert(size <= LOOKUP_MAXCLASS);
157*1208bc7eSAndroid Build Coastguard Worker 	{
158*1208bc7eSAndroid Build Coastguard Worker 		szind_t ret = (sz_size2index_tab[(size-1) >> LG_TINY_MIN]);
159*1208bc7eSAndroid Build Coastguard Worker 		assert(ret == sz_size2index_compute(size));
160*1208bc7eSAndroid Build Coastguard Worker 		return ret;
161*1208bc7eSAndroid Build Coastguard Worker 	}
162*1208bc7eSAndroid Build Coastguard Worker }
163*1208bc7eSAndroid Build Coastguard Worker 
164*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE szind_t
sz_size2index(size_t size)165*1208bc7eSAndroid Build Coastguard Worker sz_size2index(size_t size) {
166*1208bc7eSAndroid Build Coastguard Worker 	assert(size > 0);
167*1208bc7eSAndroid Build Coastguard Worker 	if (likely(size <= LOOKUP_MAXCLASS)) {
168*1208bc7eSAndroid Build Coastguard Worker 		return sz_size2index_lookup(size);
169*1208bc7eSAndroid Build Coastguard Worker 	}
170*1208bc7eSAndroid Build Coastguard Worker 	return sz_size2index_compute(size);
171*1208bc7eSAndroid Build Coastguard Worker }
172*1208bc7eSAndroid Build Coastguard Worker 
173*1208bc7eSAndroid Build Coastguard Worker static inline size_t
sz_index2size_compute(szind_t index)174*1208bc7eSAndroid Build Coastguard Worker sz_index2size_compute(szind_t index) {
175*1208bc7eSAndroid Build Coastguard Worker #if (NTBINS > 0)
176*1208bc7eSAndroid Build Coastguard Worker 	if (index < NTBINS) {
177*1208bc7eSAndroid Build Coastguard Worker 		return (ZU(1) << (LG_TINY_MAXCLASS - NTBINS + 1 + index));
178*1208bc7eSAndroid Build Coastguard Worker 	}
179*1208bc7eSAndroid Build Coastguard Worker #endif
180*1208bc7eSAndroid Build Coastguard Worker 	{
181*1208bc7eSAndroid Build Coastguard Worker 		size_t reduced_index = index - NTBINS;
182*1208bc7eSAndroid Build Coastguard Worker 		size_t grp = reduced_index >> LG_SIZE_CLASS_GROUP;
183*1208bc7eSAndroid Build Coastguard Worker 		size_t mod = reduced_index & ((ZU(1) << LG_SIZE_CLASS_GROUP) -
184*1208bc7eSAndroid Build Coastguard Worker 		    1);
185*1208bc7eSAndroid Build Coastguard Worker 
186*1208bc7eSAndroid Build Coastguard Worker 		size_t grp_size_mask = ~((!!grp)-1);
187*1208bc7eSAndroid Build Coastguard Worker 		size_t grp_size = ((ZU(1) << (LG_QUANTUM +
188*1208bc7eSAndroid Build Coastguard Worker 		    (LG_SIZE_CLASS_GROUP-1))) << grp) & grp_size_mask;
189*1208bc7eSAndroid Build Coastguard Worker 
190*1208bc7eSAndroid Build Coastguard Worker 		size_t shift = (grp == 0) ? 1 : grp;
191*1208bc7eSAndroid Build Coastguard Worker 		size_t lg_delta = shift + (LG_QUANTUM-1);
192*1208bc7eSAndroid Build Coastguard Worker 		size_t mod_size = (mod+1) << lg_delta;
193*1208bc7eSAndroid Build Coastguard Worker 
194*1208bc7eSAndroid Build Coastguard Worker 		size_t usize = grp_size + mod_size;
195*1208bc7eSAndroid Build Coastguard Worker 		return usize;
196*1208bc7eSAndroid Build Coastguard Worker 	}
197*1208bc7eSAndroid Build Coastguard Worker }
198*1208bc7eSAndroid Build Coastguard Worker 
199*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
sz_index2size_lookup(szind_t index)200*1208bc7eSAndroid Build Coastguard Worker sz_index2size_lookup(szind_t index) {
201*1208bc7eSAndroid Build Coastguard Worker 	size_t ret = (size_t)sz_index2size_tab[index];
202*1208bc7eSAndroid Build Coastguard Worker 	assert(ret == sz_index2size_compute(index));
203*1208bc7eSAndroid Build Coastguard Worker 	return ret;
204*1208bc7eSAndroid Build Coastguard Worker }
205*1208bc7eSAndroid Build Coastguard Worker 
206*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
sz_index2size(szind_t index)207*1208bc7eSAndroid Build Coastguard Worker sz_index2size(szind_t index) {
208*1208bc7eSAndroid Build Coastguard Worker 	assert(index < NSIZES);
209*1208bc7eSAndroid Build Coastguard Worker 	return sz_index2size_lookup(index);
210*1208bc7eSAndroid Build Coastguard Worker }
211*1208bc7eSAndroid Build Coastguard Worker 
212*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
sz_s2u_compute(size_t size)213*1208bc7eSAndroid Build Coastguard Worker sz_s2u_compute(size_t size) {
214*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(size > LARGE_MAXCLASS)) {
215*1208bc7eSAndroid Build Coastguard Worker 		return 0;
216*1208bc7eSAndroid Build Coastguard Worker 	}
217*1208bc7eSAndroid Build Coastguard Worker #if (NTBINS > 0)
218*1208bc7eSAndroid Build Coastguard Worker 	if (size <= (ZU(1) << LG_TINY_MAXCLASS)) {
219*1208bc7eSAndroid Build Coastguard Worker 		size_t lg_tmin = LG_TINY_MAXCLASS - NTBINS + 1;
220*1208bc7eSAndroid Build Coastguard Worker 		size_t lg_ceil = lg_floor(pow2_ceil_zu(size));
221*1208bc7eSAndroid Build Coastguard Worker 		return (lg_ceil < lg_tmin ? (ZU(1) << lg_tmin) :
222*1208bc7eSAndroid Build Coastguard Worker 		    (ZU(1) << lg_ceil));
223*1208bc7eSAndroid Build Coastguard Worker 	}
224*1208bc7eSAndroid Build Coastguard Worker #endif
225*1208bc7eSAndroid Build Coastguard Worker 	{
226*1208bc7eSAndroid Build Coastguard Worker 		size_t x = lg_floor((size<<1)-1);
227*1208bc7eSAndroid Build Coastguard Worker 		size_t lg_delta = (x < LG_SIZE_CLASS_GROUP + LG_QUANTUM + 1)
228*1208bc7eSAndroid Build Coastguard Worker 		    ?  LG_QUANTUM : x - LG_SIZE_CLASS_GROUP - 1;
229*1208bc7eSAndroid Build Coastguard Worker 		size_t delta = ZU(1) << lg_delta;
230*1208bc7eSAndroid Build Coastguard Worker 		size_t delta_mask = delta - 1;
231*1208bc7eSAndroid Build Coastguard Worker 		size_t usize = (size + delta_mask) & ~delta_mask;
232*1208bc7eSAndroid Build Coastguard Worker 		return usize;
233*1208bc7eSAndroid Build Coastguard Worker 	}
234*1208bc7eSAndroid Build Coastguard Worker }
235*1208bc7eSAndroid Build Coastguard Worker 
236*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
sz_s2u_lookup(size_t size)237*1208bc7eSAndroid Build Coastguard Worker sz_s2u_lookup(size_t size) {
238*1208bc7eSAndroid Build Coastguard Worker 	size_t ret = sz_index2size_lookup(sz_size2index_lookup(size));
239*1208bc7eSAndroid Build Coastguard Worker 
240*1208bc7eSAndroid Build Coastguard Worker 	assert(ret == sz_s2u_compute(size));
241*1208bc7eSAndroid Build Coastguard Worker 	return ret;
242*1208bc7eSAndroid Build Coastguard Worker }
243*1208bc7eSAndroid Build Coastguard Worker 
244*1208bc7eSAndroid Build Coastguard Worker /*
245*1208bc7eSAndroid Build Coastguard Worker  * Compute usable size that would result from allocating an object with the
246*1208bc7eSAndroid Build Coastguard Worker  * specified size.
247*1208bc7eSAndroid Build Coastguard Worker  */
248*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
sz_s2u(size_t size)249*1208bc7eSAndroid Build Coastguard Worker sz_s2u(size_t size) {
250*1208bc7eSAndroid Build Coastguard Worker 	assert(size > 0);
251*1208bc7eSAndroid Build Coastguard Worker 	if (likely(size <= LOOKUP_MAXCLASS)) {
252*1208bc7eSAndroid Build Coastguard Worker 		return sz_s2u_lookup(size);
253*1208bc7eSAndroid Build Coastguard Worker 	}
254*1208bc7eSAndroid Build Coastguard Worker 	return sz_s2u_compute(size);
255*1208bc7eSAndroid Build Coastguard Worker }
256*1208bc7eSAndroid Build Coastguard Worker 
257*1208bc7eSAndroid Build Coastguard Worker /*
258*1208bc7eSAndroid Build Coastguard Worker  * Compute usable size that would result from allocating an object with the
259*1208bc7eSAndroid Build Coastguard Worker  * specified size and alignment.
260*1208bc7eSAndroid Build Coastguard Worker  */
261*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
sz_sa2u(size_t size,size_t alignment)262*1208bc7eSAndroid Build Coastguard Worker sz_sa2u(size_t size, size_t alignment) {
263*1208bc7eSAndroid Build Coastguard Worker 	size_t usize;
264*1208bc7eSAndroid Build Coastguard Worker 
265*1208bc7eSAndroid Build Coastguard Worker 	assert(alignment != 0 && ((alignment - 1) & alignment) == 0);
266*1208bc7eSAndroid Build Coastguard Worker 
267*1208bc7eSAndroid Build Coastguard Worker 	/* Try for a small size class. */
268*1208bc7eSAndroid Build Coastguard Worker 	if (size <= SMALL_MAXCLASS && alignment < PAGE) {
269*1208bc7eSAndroid Build Coastguard Worker 		/*
270*1208bc7eSAndroid Build Coastguard Worker 		 * Round size up to the nearest multiple of alignment.
271*1208bc7eSAndroid Build Coastguard Worker 		 *
272*1208bc7eSAndroid Build Coastguard Worker 		 * This done, we can take advantage of the fact that for each
273*1208bc7eSAndroid Build Coastguard Worker 		 * small size class, every object is aligned at the smallest
274*1208bc7eSAndroid Build Coastguard Worker 		 * power of two that is non-zero in the base two representation
275*1208bc7eSAndroid Build Coastguard Worker 		 * of the size.  For example:
276*1208bc7eSAndroid Build Coastguard Worker 		 *
277*1208bc7eSAndroid Build Coastguard Worker 		 *   Size |   Base 2 | Minimum alignment
278*1208bc7eSAndroid Build Coastguard Worker 		 *   -----+----------+------------------
279*1208bc7eSAndroid Build Coastguard Worker 		 *     96 |  1100000 |  32
280*1208bc7eSAndroid Build Coastguard Worker 		 *    144 | 10100000 |  32
281*1208bc7eSAndroid Build Coastguard Worker 		 *    192 | 11000000 |  64
282*1208bc7eSAndroid Build Coastguard Worker 		 */
283*1208bc7eSAndroid Build Coastguard Worker 		usize = sz_s2u(ALIGNMENT_CEILING(size, alignment));
284*1208bc7eSAndroid Build Coastguard Worker 		if (usize < LARGE_MINCLASS) {
285*1208bc7eSAndroid Build Coastguard Worker 			return usize;
286*1208bc7eSAndroid Build Coastguard Worker 		}
287*1208bc7eSAndroid Build Coastguard Worker 	}
288*1208bc7eSAndroid Build Coastguard Worker 
289*1208bc7eSAndroid Build Coastguard Worker 	/* Large size class.  Beware of overflow. */
290*1208bc7eSAndroid Build Coastguard Worker 
291*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(alignment > LARGE_MAXCLASS)) {
292*1208bc7eSAndroid Build Coastguard Worker 		return 0;
293*1208bc7eSAndroid Build Coastguard Worker 	}
294*1208bc7eSAndroid Build Coastguard Worker 
295*1208bc7eSAndroid Build Coastguard Worker 	/* Make sure result is a large size class. */
296*1208bc7eSAndroid Build Coastguard Worker 	if (size <= LARGE_MINCLASS) {
297*1208bc7eSAndroid Build Coastguard Worker 		usize = LARGE_MINCLASS;
298*1208bc7eSAndroid Build Coastguard Worker 	} else {
299*1208bc7eSAndroid Build Coastguard Worker 		usize = sz_s2u(size);
300*1208bc7eSAndroid Build Coastguard Worker 		if (usize < size) {
301*1208bc7eSAndroid Build Coastguard Worker 			/* size_t overflow. */
302*1208bc7eSAndroid Build Coastguard Worker 			return 0;
303*1208bc7eSAndroid Build Coastguard Worker 		}
304*1208bc7eSAndroid Build Coastguard Worker 	}
305*1208bc7eSAndroid Build Coastguard Worker 
306*1208bc7eSAndroid Build Coastguard Worker 	/*
307*1208bc7eSAndroid Build Coastguard Worker 	 * Calculate the multi-page mapping that large_palloc() would need in
308*1208bc7eSAndroid Build Coastguard Worker 	 * order to guarantee the alignment.
309*1208bc7eSAndroid Build Coastguard Worker 	 */
310*1208bc7eSAndroid Build Coastguard Worker 	if (usize + sz_large_pad + PAGE_CEILING(alignment) - PAGE < usize) {
311*1208bc7eSAndroid Build Coastguard Worker 		/* size_t overflow. */
312*1208bc7eSAndroid Build Coastguard Worker 		return 0;
313*1208bc7eSAndroid Build Coastguard Worker 	}
314*1208bc7eSAndroid Build Coastguard Worker 	return usize;
315*1208bc7eSAndroid Build Coastguard Worker }
316*1208bc7eSAndroid Build Coastguard Worker 
317*1208bc7eSAndroid Build Coastguard Worker #endif /* JEMALLOC_INTERNAL_SIZE_H */
318