Skip to content

Commit 4ac0858

Browse files
authored
Merge pull request #64 from thomcc/improve-global-alloc
Improve our GlobalAlloc impl
2 parents dcadf23 + 8cb9a1a commit 4ac0858

File tree

1 file changed

+29
-33
lines changed

1 file changed

+29
-33
lines changed

src/lib.rs

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,32 @@ use core::alloc::{GlobalAlloc, Layout};
2929
use core::ffi::c_void;
3030
use ffi::*;
3131

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+
}
5258

5359
/// Drop-in mimalloc global allocator.
5460
///
@@ -64,28 +70,18 @@ pub struct MiMalloc;
6470
unsafe impl GlobalAlloc for MiMalloc {
6571
#[inline]
6672
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()) {
6874
mi_malloc(layout.size()) as *mut u8
6975
} else {
70-
#[cfg(target_os = "macos")]
71-
if layout.align() > (1 << 31) {
72-
return core::ptr::null_mut();
73-
}
74-
7576
mi_malloc_aligned(layout.size(), layout.align()) as *mut u8
7677
}
7778
}
7879

7980
#[inline]
8081
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()) {
8283
mi_zalloc(layout.size()) as *mut u8
8384
} else {
84-
#[cfg(target_os = "macos")]
85-
if layout.align() > (1 << 31) {
86-
return core::ptr::null_mut();
87-
}
88-
8985
mi_zalloc_aligned(layout.size(), layout.align()) as *mut u8
9086
}
9187
}
@@ -97,7 +93,7 @@ unsafe impl GlobalAlloc for MiMalloc {
9793

9894
#[inline]
9995
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()) {
10197
mi_realloc(ptr as *mut c_void, new_size) as *mut u8
10298
} else {
10399
mi_realloc_aligned(ptr as *mut c_void, new_size, layout.align()) as *mut u8

0 commit comments

Comments
 (0)