@@ -29,26 +29,32 @@ use core::alloc::{GlobalAlloc, Layout};
29
29
use core:: ffi:: c_void;
30
30
use ffi:: * ;
31
31
32
- // Copied from https://github.com/rust-lang/rust/blob/master/src/libstd/sys_common/alloc.rs
33
- #[ cfg( all( any(
34
- target_arch = "x86" ,
35
- target_arch = "arm" ,
36
- target_arch = "mips" ,
37
- target_arch = "powerpc" ,
38
- target_arch = "powerpc64" ,
39
- target_arch = "asmjs" ,
40
- target_arch = "wasm32"
41
- ) ) ) ]
42
- const MIN_ALIGN : usize = 8 ;
43
-
44
- #[ cfg( all( any(
45
- target_arch = "x86_64" ,
46
- target_arch = "aarch64" ,
47
- target_arch = "mips64" ,
48
- target_arch = "s390x" ,
49
- target_arch = "sparc64"
50
- ) ) ) ]
51
- const MIN_ALIGN : usize = 16 ;
32
+ // `MI_MAX_ALIGN_SIZE` is 16 unless manually overridden:
33
+ // https://github.com/microsoft/mimalloc/blob/15220c68/include/mimalloc-types.h#L22
34
+ //
35
+ // If it changes on us, we should consider either manually overriding it, or
36
+ // expose it from the -sys crate (in order to catch updates)
37
+ const MI_MAX_ALIGN_SIZE : usize = 16 ;
38
+
39
+ // Note: this doesn't take a layout directly because doing so would be wrong for
40
+ // reallocation
41
+ #[ inline]
42
+ fn may_use_unaligned_api ( size : usize , alignment : usize ) -> bool {
43
+ // Required by `GlobalAlloc`. Note that while allocators aren't allowed to
44
+ // unwind in rust, this is only in debug mode, and can only happen if the
45
+ // caller already caused UB by passing in an invalid layout.
46
+ debug_assert ! ( size != 0 && alignment. is_power_of_two( ) ) ;
47
+
48
+ // This logic is based on the discussion [here]. We don't bother with the
49
+ // 3rd suggested test due to it being high cost (calling `mi_good_size`)
50
+ // compared to the other checks, and also feeling like it relies on too much
51
+ // implementation-specific behavior.
52
+ //
53
+ // [here]: https://github.com/microsoft/mimalloc/issues/314#issuecomment-708541845
54
+
55
+ ( alignment <= MI_MAX_ALIGN_SIZE && size >= alignment)
56
+ || ( alignment == size && alignment <= 4096 )
57
+ }
52
58
53
59
/// Drop-in mimalloc global allocator.
54
60
///
@@ -64,28 +70,18 @@ pub struct MiMalloc;
64
70
unsafe impl GlobalAlloc for MiMalloc {
65
71
#[ inline]
66
72
unsafe fn alloc ( & self , layout : Layout ) -> * mut u8 {
67
- if layout. align ( ) <= MIN_ALIGN && layout. align ( ) <= layout . size ( ) {
73
+ if may_use_unaligned_api ( layout. size ( ) , layout. align ( ) ) {
68
74
mi_malloc ( layout. size ( ) ) as * mut u8
69
75
} else {
70
- #[ cfg( target_os = "macos" ) ]
71
- if layout. align ( ) > ( 1 << 31 ) {
72
- return core:: ptr:: null_mut ( ) ;
73
- }
74
-
75
76
mi_malloc_aligned ( layout. size ( ) , layout. align ( ) ) as * mut u8
76
77
}
77
78
}
78
79
79
80
#[ inline]
80
81
unsafe fn alloc_zeroed ( & self , layout : Layout ) -> * mut u8 {
81
- if layout. align ( ) <= MIN_ALIGN && layout. align ( ) <= layout . size ( ) {
82
+ if may_use_unaligned_api ( layout. size ( ) , layout. align ( ) ) {
82
83
mi_zalloc ( layout. size ( ) ) as * mut u8
83
84
} else {
84
- #[ cfg( target_os = "macos" ) ]
85
- if layout. align ( ) > ( 1 << 31 ) {
86
- return core:: ptr:: null_mut ( ) ;
87
- }
88
-
89
85
mi_zalloc_aligned ( layout. size ( ) , layout. align ( ) ) as * mut u8
90
86
}
91
87
}
@@ -97,7 +93,7 @@ unsafe impl GlobalAlloc for MiMalloc {
97
93
98
94
#[ inline]
99
95
unsafe fn realloc ( & self , ptr : * mut u8 , layout : Layout , new_size : usize ) -> * mut u8 {
100
- if layout . align ( ) <= MIN_ALIGN && layout. align ( ) <= layout . size ( ) {
96
+ if may_use_unaligned_api ( new_size , layout. align ( ) ) {
101
97
mi_realloc ( ptr as * mut c_void , new_size) as * mut u8
102
98
} else {
103
99
mi_realloc_aligned ( ptr as * mut c_void , new_size, layout. align ( ) ) as * mut u8
0 commit comments