1#![no_std]
2
3extern crate loca;
4
5use core::ptr::NonNull;
6use loca::*;
7
8use c::*;
9
10mod c {
11 extern "C" {
25 #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
26 target_os = "dragonfly", target_os = "windows", target_env = "musl"),
27 link_name = "je_mallocx")]
28 pub fn mallocx(size: usize, flags: usize) -> *mut u8;
29 #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
30 target_os = "dragonfly", target_os = "windows", target_env = "musl"),
31 link_name = "je_rallocx")]
32 pub fn rallocx(ptr: *mut u8, size: usize, flags: usize) -> *mut u8;
33 #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
34 target_os = "dragonfly", target_os = "windows", target_env = "musl"),
35 link_name = "je_xallocx")]
36 pub fn xallocx(ptr: *mut u8, size: usize, extra: usize, flags: usize) -> usize;
37 #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
38 target_os = "dragonfly", target_os = "windows", target_env = "musl"),
39 link_name = "je_sdallocx")]
40 pub fn sdallocx(ptr: *mut u8, size: usize, flags: usize);
41 #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
42 target_os = "dragonfly", target_os = "windows", target_env = "musl"),
43 link_name = "je_nallocx")]
44 pub fn nallocx(size: usize, flags: usize) -> usize;
45 }
46}
47
48#[derive(Clone, Copy, Default, Debug)]
49pub struct Jemalloc;
50
51use AllocErr::*;
52
53const MALLOCX_ZERO: usize = 0x40;
54
55unsafe impl Alloc for Jemalloc {
56 #[inline]
57 unsafe fn alloc(&mut self, l: Layout) -> Result<NonNull<u8>, AllocErr> {
58 NonNull::new(mallocx(l.size(), l.align().get().trailing_zeros() as _))
59 .ok_or(Exhausted { request: l })
60 }
61
62 #[inline]
63 unsafe fn alloc_zeroed(&mut self, l: Layout) -> Result<NonNull<u8>, AllocErr> {
64 NonNull::new(mallocx(l.size(), l.align().get().trailing_zeros() as usize | MALLOCX_ZERO))
65 .ok_or(Exhausted { request: l })
66 }
67
68 #[inline]
69 unsafe fn realloc(&mut self, ptr: NonNull<u8>, old_l: Layout, new_size: usize) -> Result<NonNull<u8>, AllocErr> {
70 NonNull::new(rallocx(ptr.as_ptr(), new_size, old_l.align().get().trailing_zeros() as _))
71 .ok_or(Exhausted { request: Layout::from_size_align(new_size, old_l.align().get()).unwrap() })
72 }
73
74 #[inline]
75 unsafe fn dealloc(&mut self, ptr: NonNull<u8>, l: Layout) {
76 sdallocx(ptr.as_ptr(), l.size(), l.align().get().trailing_zeros() as _)
77 }
78
79 #[inline]
80 unsafe fn resize_in_place(&mut self, ptr: NonNull<u8>, old_l: Layout, new_size: usize) -> Result<(), CannotReallocInPlace> {
81 if new_size ==
82 xallocx(ptr.as_ptr(), new_size, 0, old_l.align().get().trailing_zeros() as _) { Ok(()) }
83 else { Err(CannotReallocInPlace) }
84 }
85
86 #[inline]
87 fn usable_size(&self, l: Layout) -> (usize, usize) {
88 (l.size(), ::core::cmp::max(l.size(), unsafe {
89 nallocx(l.size(), l.align().get().trailing_zeros() as _)
90 }))
91 }
92}