11use std:: {
22 alloc:: { Layout , alloc, dealloc, realloc} ,
33 ptr:: null_mut,
4+ sync:: OnceLock ,
45} ;
56
67use flecs_ecs:: sys:: {
@@ -9,18 +10,23 @@ use flecs_ecs::sys::{
910
1011const ALIGNMENT : usize = 64 ;
1112
12- // Store size in a prefix, perfectly aligned
13- #[ repr( C , align( 64 ) ) ] // Ensure the header itself is aligned
14- struct AllocHeader {
15- size : usize ,
13+ // Global size tracker using papaya HashMap
14+ static ALLOC_SIZES : OnceLock < papaya:: HashMap < usize , usize > > = OnceLock :: new ( ) ;
15+
16+ fn init_size_map ( ) {
17+ ALLOC_SIZES . get_or_init ( papaya:: HashMap :: new) ;
18+ }
19+
20+ fn get_size_map ( ) -> & ' static papaya:: HashMap < usize , usize > {
21+ unsafe { ALLOC_SIZES . get ( ) . unwrap_unchecked ( ) }
1622}
1723
1824unsafe extern "C-unwind" fn aligned_malloc ( size : ecs_size_t ) -> * mut core:: ffi:: c_void {
1925 #[ allow( clippy:: cast_possible_wrap, clippy:: cast_sign_loss) ]
20- let total_size = size as usize + size_of :: < AllocHeader > ( ) ;
26+ let size = size as usize ;
2127
2228 // Allocate with our desired alignment
23- let Ok ( layout) = Layout :: from_size_align ( total_size , ALIGNMENT ) else {
29+ let Ok ( layout) = Layout :: from_size_align ( size , ALIGNMENT ) else {
2430 return null_mut ( ) ;
2531 } ;
2632
@@ -29,26 +35,16 @@ unsafe extern "C-unwind" fn aligned_malloc(size: ecs_size_t) -> *mut core::ffi::
2935 return null_mut ( ) ;
3036 }
3137
32- // Write the header
33- #[ allow( clippy:: cast_ptr_alignment) ]
34- let header = ptr. cast :: < AllocHeader > ( ) ;
38+ // Store the size in our global map
39+ get_size_map ( ) . pin ( ) . insert ( ptr as usize , size) ;
3540
36- #[ allow( clippy:: cast_possible_wrap, clippy:: cast_sign_loss) ]
37- unsafe {
38- ( * header) . size = size as usize ;
39- } ;
40-
41- // Return pointer after the header
42- unsafe {
43- ptr. add ( size_of :: < AllocHeader > ( ) )
44- . cast :: < core:: ffi:: c_void > ( )
45- }
41+ ptr. cast :: < core:: ffi:: c_void > ( )
4642}
4743
4844unsafe extern "C-unwind" fn aligned_calloc ( size : ecs_size_t ) -> * mut core:: ffi:: c_void {
4945 let ptr = unsafe { aligned_malloc ( size) } ;
5046 if !ptr. is_null ( ) {
51- // Zero only the user data portion, header already contains size
47+ // Zero the entire allocation
5248 #[ allow( clippy:: cast_possible_wrap, clippy:: cast_sign_loss) ]
5349 unsafe {
5450 std:: ptr:: write_bytes ( ptr, 0 , size as usize ) ;
@@ -65,68 +61,50 @@ unsafe extern "C-unwind" fn aligned_realloc(
6561 return unsafe { aligned_malloc ( new_size) } ;
6662 }
6763
68- // Get the header pointer from the user pointer
69- #[ allow( clippy:: cast_ptr_alignment) ]
70- let header_ptr = unsafe {
71- ptr. cast :: < u8 > ( )
72- . sub ( size_of :: < AllocHeader > ( ) )
73- . cast :: < AllocHeader > ( )
74- } ;
75- let old_size = unsafe { ( * header_ptr) . size } ;
76-
7764 #[ allow( clippy:: cast_possible_wrap, clippy:: cast_sign_loss) ]
78- let total_new_size = new_size as usize + size_of :: < AllocHeader > ( ) ;
65+ let new_size = new_size as usize ;
7966
80- // Reallocate with the total size
81- let layout = unsafe {
82- Layout :: from_size_align_unchecked ( old_size + size_of :: < AllocHeader > ( ) , ALIGNMENT )
83- } ;
67+ let size_map = get_size_map ( ) . pin ( ) ;
68+
69+ // Get the old size from our map
70+ let old_size = size_map . get ( & ( ptr as usize ) ) . copied ( ) . unwrap_or ( 0 ) ;
8471
85- let new_ptr = unsafe { realloc ( header_ptr. cast :: < u8 > ( ) , layout, total_new_size) } ;
72+ // Create layout for reallocation
73+ let layout = unsafe { Layout :: from_size_align_unchecked ( old_size, ALIGNMENT ) } ;
8674
75+ let new_ptr = unsafe { realloc ( ptr. cast :: < u8 > ( ) , layout, new_size) } ;
8776 if new_ptr. is_null ( ) {
8877 return null_mut ( ) ;
8978 }
9079
91- // Update size in header
92- #[ allow( clippy:: cast_ptr_alignment) ]
93- let new_header = new_ptr. cast :: < AllocHeader > ( ) ;
94-
95- #[ allow( clippy:: cast_possible_wrap, clippy:: cast_sign_loss) ]
96- unsafe {
97- ( * new_header) . size = new_size as usize ;
98- } ;
80+ // Update size in map
81+ size_map. remove ( & ( ptr as usize ) ) ;
82+ size_map. insert ( new_ptr as usize , new_size) ;
9983
100- // Return pointer after header
101- unsafe {
102- new_ptr
103- . add ( size_of :: < AllocHeader > ( ) )
104- . cast :: < core:: ffi:: c_void > ( )
105- }
84+ new_ptr. cast :: < core:: ffi:: c_void > ( )
10685}
10786
10887unsafe extern "C-unwind" fn aligned_free ( ptr : * mut core:: ffi:: c_void ) {
10988 if !ptr. is_null ( ) {
110- // Get the header pointer
111- let header_ptr = unsafe { ptr. cast :: < u8 > ( ) . sub ( size_of :: < AllocHeader > ( ) ) } ;
112-
113- #[ allow( clippy:: cast_ptr_alignment) ]
114- let header = header_ptr. cast :: < AllocHeader > ( ) ;
115- let total_size = unsafe { ( * header) . size + size_of :: < AllocHeader > ( ) } ;
116-
117- // Deallocate the entire block
118- let layout = unsafe { Layout :: from_size_align_unchecked ( total_size, ALIGNMENT ) } ;
119- unsafe { dealloc ( header_ptr, layout) } ;
89+ let size_map = get_size_map ( ) . pin ( ) ;
90+ // Get the size from our map
91+ if let Some ( size) = size_map. remove ( & ( ptr as usize ) ) {
92+ // Deallocate the block
93+ let layout = unsafe { Layout :: from_size_align_unchecked ( * size, ALIGNMENT ) } ;
94+ unsafe { dealloc ( ptr. cast :: < u8 > ( ) , layout) } ;
95+ }
12096 }
12197}
12298
123- // Setup function remains the same
12499pub fn setup_custom_allocators ( ) -> (
125100 ecs_os_api_malloc_t ,
126101 ecs_os_api_calloc_t ,
127102 ecs_os_api_realloc_t ,
128103 ecs_os_api_free_t ,
129104) {
105+ // Initialize the global size map if not already initialized
106+ init_size_map ( ) ;
107+
130108 (
131109 Some ( aligned_malloc) ,
132110 Some ( aligned_calloc) ,
0 commit comments