@@ -275,14 +275,20 @@ static inline mi_segment_t* _mi_page_segment(const mi_page_t* page) {
275275 return segment ;
276276}
277277
278- // Get the page containing the pointer
279- static inline mi_page_t * _mi_segment_page_of (const mi_segment_t * segment , const void * p ) {
278+ // used internally
279+ static inline uintptr_t _mi_segment_page_idx_of (const mi_segment_t * segment , const void * p ) {
280280 // if (segment->page_size > MI_SEGMENT_SIZE) return &segment->pages[0]; // huge pages
281281 ptrdiff_t diff = (uint8_t * )p - (uint8_t * )segment ;
282282 mi_assert_internal (diff >= 0 && diff < MI_SEGMENT_SIZE );
283283 uintptr_t idx = (uintptr_t )diff >> segment -> page_shift ;
284284 mi_assert_internal (idx < segment -> capacity );
285285 mi_assert_internal (segment -> page_kind <= MI_PAGE_MEDIUM || idx == 0 );
286+ return idx ;
287+ }
288+
289+ // Get the page containing the pointer
290+ static inline mi_page_t * _mi_segment_page_of (const mi_segment_t * segment , const void * p ) {
291+ uintptr_t idx = _mi_segment_page_idx_of (segment , p );
286292 return & ((mi_segment_t * )segment )-> pages [idx ];
287293}
288294
@@ -373,53 +379,67 @@ static inline void mi_page_set_has_aligned(mi_page_t* page, bool has_aligned) {
373379
374380// -------------------------------------------------------------------
375381// Encoding/Decoding the free list next pointers
382+ // Note: we pass a `null` value to be used as the `NULL` value for the
383+ // end of a free list. This is to prevent the cookie itself to ever
384+ // be present among user blocks (as `cookie^0==cookie`).
376385// -------------------------------------------------------------------
377386
378387static inline bool mi_is_in_same_segment (const void * p , const void * q ) {
379388 return (_mi_ptr_segment (p ) == _mi_ptr_segment (q ));
380389}
381390
382- static inline mi_block_t * mi_block_nextx ( uintptr_t cookie , const mi_block_t * block ) {
391+ static inline bool mi_is_in_same_page (const void * p , const void * q ) {
392+ mi_segment_t * segmentp = _mi_ptr_segment (p );
393+ mi_segment_t * segmentq = _mi_ptr_segment (q );
394+ if (segmentp != segmentq ) return false;
395+ uintptr_t idxp = _mi_segment_page_idx_of (segmentp , p );
396+ uintptr_t idxq = _mi_segment_page_idx_of (segmentq , q );
397+ return (idxp == idxq );
398+ }
399+
400+ static inline mi_block_t * mi_block_nextx ( const void * null , const mi_block_t * block , uintptr_t cookie ) {
383401 #ifdef MI_ENCODE_FREELIST
384- return (mi_block_t * )(block -> next ^ cookie );
402+ mi_block_t * b = (mi_block_t * )(block -> next ^ cookie );
403+ if (mi_unlikely ((void * )b == null )) { b = NULL ; }
404+ return b ;
385405 #else
386- UNUSED (cookie );
406+ UNUSED (cookie ); UNUSED ( null );
387407 return (mi_block_t * )block -> next ;
388408 #endif
389409}
390410
391- static inline void mi_block_set_nextx (uintptr_t cookie , mi_block_t * block , const mi_block_t * next ) {
411+ static inline void mi_block_set_nextx (const void * null , mi_block_t * block , const mi_block_t * next , uintptr_t cookie ) {
392412 #ifdef MI_ENCODE_FREELIST
413+ if (mi_unlikely (next == NULL )) { next = (mi_block_t * )null ; }
393414 block -> next = (mi_encoded_t )next ^ cookie ;
394415 #else
395- UNUSED (cookie );
416+ UNUSED (cookie ); UNUSED ( null );
396417 block -> next = (mi_encoded_t )next ;
397418 #endif
398419}
399420
400421static inline mi_block_t * mi_block_next (const mi_page_t * page , const mi_block_t * block ) {
401422 #ifdef MI_ENCODE_FREELIST
402- mi_block_t * next = mi_block_nextx (page -> cookie , block );
423+ mi_block_t * next = mi_block_nextx (page , block , page -> cookie );
403424 // check for free list corruption: is `next` at least in our segment range?
404- // TODO: it is better to check if it is actually inside our page but that is more expensive
405- // to calculate. Perhaps with a relative free list this becomes feasible?
406- if (next != NULL && !mi_is_in_same_segment (block , next )) {
425+ // TODO: check if `next` is `page->block_size` aligned?
426+ if (next != NULL && !mi_is_in_same_page (block , next )) {
407427 _mi_fatal_error ("corrupted free list entry of size %zub at %p: value 0x%zx\n" , page -> block_size , block , (uintptr_t )next );
408428 next = NULL ;
409429 }
410430 return next ;
411431 #else
412432 UNUSED (page );
413- return mi_block_nextx (0 , block );
433+ return mi_block_nextx (page , block , 0 );
414434 #endif
415435}
416436
417437static inline void mi_block_set_next (const mi_page_t * page , mi_block_t * block , const mi_block_t * next ) {
418438 #ifdef MI_ENCODE_FREELIST
419- mi_block_set_nextx (page -> cookie ,block ,next );
439+ mi_block_set_nextx (page ,block ,next , page -> cookie );
420440 #else
421441 UNUSED (page );
422- mi_block_set_nextx (0 , block , next );
442+ mi_block_set_nextx (page , block , next , 0 );
423443 #endif
424444}
425445
0 commit comments