@@ -6,9 +6,10 @@ terms of the MIT license. A copy of the license can be found in the file
6
6
-----------------------------------------------------------------------------*/
7
7
8
8
#include "mimalloc.h"
9
- #include "mimalloc-internal.h"
9
+ #include "mimalloc/internal.h"
10
+ #include "mimalloc/prim.h" // mi_prim_get_default_heap
10
11
11
- #include <string.h> // memset
12
+ #include <string.h> // memset
12
13
13
14
// ------------------------------------------------------
14
15
// Aligned Allocation
@@ -61,52 +62,44 @@ static mi_decl_noinline void* mi_heap_malloc_zero_aligned_at_fallback(mi_heap_t*
61
62
mi_assert_internal (adjust < alignment );
62
63
void * aligned_p = (void * )((uintptr_t )p + adjust );
63
64
if (aligned_p != p ) {
64
- mi_page_set_has_aligned (_mi_ptr_page (p ), true);
65
+ mi_page_t * page = _mi_ptr_page (p );
66
+ mi_page_set_has_aligned (page , true);
67
+ _mi_padding_shrink (page , (mi_block_t * )p , adjust + size );
65
68
}
69
+ // todo: expand padding if overallocated ?
66
70
67
71
mi_assert_internal (mi_page_usable_block_size (_mi_ptr_page (p )) >= adjust + size );
68
72
mi_assert_internal (p == _mi_page_ptr_unalign (_mi_ptr_segment (aligned_p ), _mi_ptr_page (aligned_p ), aligned_p ));
69
73
mi_assert_internal (((uintptr_t )aligned_p + offset ) % alignment == 0 );
70
- mi_assert_internal (mi_page_usable_block_size (_mi_ptr_page (p )) >= adjust + size );
74
+ mi_assert_internal (mi_usable_size (aligned_p )>=size );
75
+ mi_assert_internal (mi_usable_size (p ) == mi_usable_size (aligned_p )+ adjust );
71
76
72
77
// now zero the block if needed
73
- if (zero && alignment > MI_ALIGNMENT_MAX ) {
74
- const ptrdiff_t diff = (uint8_t * )aligned_p - (uint8_t * )p ;
75
- const ptrdiff_t zsize = mi_page_usable_block_size (_mi_ptr_page (p )) - diff - MI_PADDING_SIZE ;
76
- if (zsize > 0 ) { _mi_memzero (aligned_p , zsize ); }
78
+ if (alignment > MI_ALIGNMENT_MAX ) {
79
+ // for the tracker, on huge aligned allocations only from the start of the large block is defined
80
+ mi_track_mem_undefined (aligned_p , size );
81
+ if (zero ) {
82
+ _mi_memzero_aligned (aligned_p , mi_usable_size (aligned_p ));
83
+ }
77
84
}
78
85
79
- #if MI_TRACK_ENABLED
80
86
if (p != aligned_p ) {
81
- mi_track_free_size (p , oversize );
82
- mi_track_malloc (aligned_p , size , zero );
83
- }
84
- else {
85
- mi_track_resize (aligned_p , oversize , size );
87
+ mi_track_align (p ,aligned_p ,adjust ,mi_usable_size (aligned_p ));
86
88
}
87
- #endif
88
89
return aligned_p ;
89
90
}
90
91
91
92
// Primitive aligned allocation
92
93
static void * mi_heap_malloc_zero_aligned_at (mi_heap_t * const heap , const size_t size , const size_t alignment , const size_t offset , const bool zero ) mi_attr_noexcept
93
94
{
94
95
// note: we don't require `size > offset`, we just guarantee that the address at offset is aligned regardless of the allocated size.
95
- mi_assert (alignment > 0 );
96
96
if mi_unlikely (alignment == 0 || !_mi_is_power_of_two (alignment )) { // require power-of-two (see <https://en.cppreference.com/w/c/memory/aligned_alloc>)
97
97
#if MI_DEBUG > 0
98
98
_mi_error_message (EOVERFLOW , "aligned allocation requires the alignment to be a power-of-two (size %zu, alignment %zu)\n" , size , alignment );
99
99
#endif
100
100
return NULL ;
101
101
}
102
- /*
103
- if mi_unlikely(alignment > MI_ALIGNMENT_MAX) { // we cannot align at a boundary larger than this (or otherwise we cannot find segment headers)
104
- #if MI_DEBUG > 0
105
- _mi_error_message(EOVERFLOW, "aligned allocation has a maximum alignment of %zu (size %zu, alignment %zu)\n", MI_ALIGNMENT_MAX, size, alignment);
106
- #endif
107
- return NULL;
108
- }
109
- */
102
+
110
103
if mi_unlikely (size > PTRDIFF_MAX ) { // we don't allocate more than PTRDIFF_MAX (see <https://sourceware.org/ml/libc-announce/2019/msg00001.html>)
111
104
#if MI_DEBUG > 0
112
105
_mi_error_message (EOVERFLOW , "aligned allocation request is too large (size %zu, alignment %zu)\n" , size , alignment );
@@ -146,9 +139,9 @@ mi_decl_nodiscard mi_decl_restrict void* mi_heap_malloc_aligned_at(mi_heap_t* he
146
139
}
147
140
148
141
mi_decl_nodiscard mi_decl_restrict void * mi_heap_malloc_aligned (mi_heap_t * heap , size_t size , size_t alignment ) mi_attr_noexcept {
142
+ if mi_unlikely (alignment == 0 || !_mi_is_power_of_two (alignment )) return NULL ;
149
143
#if !MI_PADDING
150
144
// without padding, any small sized allocation is naturally aligned (see also `_mi_segment_page_start`)
151
- if (!_mi_is_power_of_two (alignment )) return NULL ;
152
145
if mi_likely (_mi_is_power_of_two (size ) && size >= alignment && size <= MI_SMALL_SIZE_MAX )
153
146
#else
154
147
// with padding, we can only guarantee this for fixed alignments
@@ -164,6 +157,11 @@ mi_decl_nodiscard mi_decl_restrict void* mi_heap_malloc_aligned(mi_heap_t* heap,
164
157
}
165
158
}
166
159
160
+ // ensure a definition is emitted
161
+ #if defined(__cplusplus )
162
+ static void * _mi_heap_malloc_aligned = (void * )& mi_heap_malloc_aligned ;
163
+ #endif
164
+
167
165
// ------------------------------------------------------
168
166
// Aligned Allocation
169
167
// ------------------------------------------------------
@@ -187,27 +185,27 @@ mi_decl_nodiscard mi_decl_restrict void* mi_heap_calloc_aligned(mi_heap_t* heap,
187
185
}
188
186
189
187
mi_decl_nodiscard mi_decl_restrict void * mi_malloc_aligned_at (size_t size , size_t alignment , size_t offset ) mi_attr_noexcept {
190
- return mi_heap_malloc_aligned_at (mi_get_default_heap (), size , alignment , offset );
188
+ return mi_heap_malloc_aligned_at (mi_prim_get_default_heap (), size , alignment , offset );
191
189
}
192
190
193
191
mi_decl_nodiscard mi_decl_restrict void * mi_malloc_aligned (size_t size , size_t alignment ) mi_attr_noexcept {
194
- return mi_heap_malloc_aligned (mi_get_default_heap (), size , alignment );
192
+ return mi_heap_malloc_aligned (mi_prim_get_default_heap (), size , alignment );
195
193
}
196
194
197
195
mi_decl_nodiscard mi_decl_restrict void * mi_zalloc_aligned_at (size_t size , size_t alignment , size_t offset ) mi_attr_noexcept {
198
- return mi_heap_zalloc_aligned_at (mi_get_default_heap (), size , alignment , offset );
196
+ return mi_heap_zalloc_aligned_at (mi_prim_get_default_heap (), size , alignment , offset );
199
197
}
200
198
201
199
mi_decl_nodiscard mi_decl_restrict void * mi_zalloc_aligned (size_t size , size_t alignment ) mi_attr_noexcept {
202
- return mi_heap_zalloc_aligned (mi_get_default_heap (), size , alignment );
200
+ return mi_heap_zalloc_aligned (mi_prim_get_default_heap (), size , alignment );
203
201
}
204
202
205
203
mi_decl_nodiscard mi_decl_restrict void * mi_calloc_aligned_at (size_t count , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept {
206
- return mi_heap_calloc_aligned_at (mi_get_default_heap (), count , size , alignment , offset );
204
+ return mi_heap_calloc_aligned_at (mi_prim_get_default_heap (), count , size , alignment , offset );
207
205
}
208
206
209
207
mi_decl_nodiscard mi_decl_restrict void * mi_calloc_aligned (size_t count , size_t size , size_t alignment ) mi_attr_noexcept {
210
- return mi_heap_calloc_aligned (mi_get_default_heap (), count , size , alignment );
208
+ return mi_heap_calloc_aligned (mi_prim_get_default_heap (), count , size , alignment );
211
209
}
212
210
213
211
@@ -225,19 +223,13 @@ static void* mi_heap_realloc_zero_aligned_at(mi_heap_t* heap, void* p, size_t ne
225
223
return p ; // reallocation still fits, is aligned and not more than 50% waste
226
224
}
227
225
else {
226
+ // note: we don't zero allocate upfront so we only zero initialize the expanded part
228
227
void * newp = mi_heap_malloc_aligned_at (heap ,newsize ,alignment ,offset );
229
228
if (newp != NULL ) {
230
229
if (zero && newsize > size ) {
231
- const mi_page_t * page = _mi_ptr_page (newp );
232
- if (page -> is_zero ) {
233
- // already zero initialized
234
- mi_assert_expensive (mi_mem_is_zero (newp ,newsize ));
235
- }
236
- else {
237
- // also set last word in the previous allocation to zero to ensure any padding is zero-initialized
238
- size_t start = (size >= sizeof (intptr_t ) ? size - sizeof (intptr_t ) : 0 );
239
- memset ((uint8_t * )newp + start , 0 , newsize - start );
240
- }
230
+ // also set last word in the previous allocation to zero to ensure any padding is zero-initialized
231
+ size_t start = (size >= sizeof (intptr_t ) ? size - sizeof (intptr_t ) : 0 );
232
+ _mi_memzero ((uint8_t * )newp + start , newsize - start );
241
233
}
242
234
_mi_memcpy_aligned (newp , p , (newsize > size ? size : newsize ));
243
235
mi_free (p ); // only free if successful
@@ -282,25 +274,25 @@ mi_decl_nodiscard void* mi_heap_recalloc_aligned(mi_heap_t* heap, void* p, size_
282
274
}
283
275
284
276
mi_decl_nodiscard void * mi_realloc_aligned_at (void * p , size_t newsize , size_t alignment , size_t offset ) mi_attr_noexcept {
285
- return mi_heap_realloc_aligned_at (mi_get_default_heap (), p , newsize , alignment , offset );
277
+ return mi_heap_realloc_aligned_at (mi_prim_get_default_heap (), p , newsize , alignment , offset );
286
278
}
287
279
288
280
mi_decl_nodiscard void * mi_realloc_aligned (void * p , size_t newsize , size_t alignment ) mi_attr_noexcept {
289
- return mi_heap_realloc_aligned (mi_get_default_heap (), p , newsize , alignment );
281
+ return mi_heap_realloc_aligned (mi_prim_get_default_heap (), p , newsize , alignment );
290
282
}
291
283
292
284
mi_decl_nodiscard void * mi_rezalloc_aligned_at (void * p , size_t newsize , size_t alignment , size_t offset ) mi_attr_noexcept {
293
- return mi_heap_rezalloc_aligned_at (mi_get_default_heap (), p , newsize , alignment , offset );
285
+ return mi_heap_rezalloc_aligned_at (mi_prim_get_default_heap (), p , newsize , alignment , offset );
294
286
}
295
287
296
288
mi_decl_nodiscard void * mi_rezalloc_aligned (void * p , size_t newsize , size_t alignment ) mi_attr_noexcept {
297
- return mi_heap_rezalloc_aligned (mi_get_default_heap (), p , newsize , alignment );
289
+ return mi_heap_rezalloc_aligned (mi_prim_get_default_heap (), p , newsize , alignment );
298
290
}
299
291
300
292
mi_decl_nodiscard void * mi_recalloc_aligned_at (void * p , size_t newcount , size_t size , size_t alignment , size_t offset ) mi_attr_noexcept {
301
- return mi_heap_recalloc_aligned_at (mi_get_default_heap (), p , newcount , size , alignment , offset );
293
+ return mi_heap_recalloc_aligned_at (mi_prim_get_default_heap (), p , newcount , size , alignment , offset );
302
294
}
303
295
304
296
mi_decl_nodiscard void * mi_recalloc_aligned (void * p , size_t newcount , size_t size , size_t alignment ) mi_attr_noexcept {
305
- return mi_heap_recalloc_aligned (mi_get_default_heap (), p , newcount , size , alignment );
297
+ return mi_heap_recalloc_aligned (mi_prim_get_default_heap (), p , newcount , size , alignment );
306
298
}
0 commit comments