From d1c0eb9f2c02af7a91399605a661119f9a8413f4 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Fri, 25 Aug 2017 17:38:37 -0700 Subject: [PATCH] Add liballoc_system shim --- .gitignore | 3 ++ Cargo.toml | 1 + src/alloc.rs | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 +- 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 src/alloc.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..6aa106405a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target/ +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 4603191bff0..f0715992f12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ repository = "https://github.com/Manishearth/hashglobe" readme = "README.md" [dependencies] +libc = "0.2" \ No newline at end of file diff --git a/src/alloc.rs b/src/alloc.rs new file mode 100644 index 00000000000..7a961ea6323 --- /dev/null +++ b/src/alloc.rs @@ -0,0 +1,148 @@ + + +// The minimum alignment guaranteed by the architecture. This value is used to +// add fast paths for low alignment values. In practice, the alignment is a +// constant at the call site and the branch will be optimized out. +#[cfg(all(any(target_arch = "x86", + target_arch = "arm", + target_arch = "mips", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "asmjs", + target_arch = "wasm32")))] +const MIN_ALIGN: usize = 8; +#[cfg(all(any(target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64")))] +const MIN_ALIGN: usize = 16; + +pub use self::platform::{alloc, dealloc}; + +#[cfg(any(unix, target_os = "redox"))] +mod platform { + extern crate libc; + + use std::ptr; + + use super::MIN_ALIGN; + + #[inline] + pub unsafe fn alloc(size: usize, align: usize) -> *mut u8 { + let ptr = if align <= MIN_ALIGN { + libc::malloc(size) as *mut u8 + } else { + aligned_malloc(size, align) + }; + ptr + } + + #[inline] + pub unsafe fn dealloc(ptr: *mut u8, _align: usize) { + libc::free(ptr as *mut libc::c_void) + } + + #[cfg(any(target_os = "android", target_os = "redox"))] + #[inline] + unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { + // On android we currently target API level 9 which unfortunately + // doesn't have the `posix_memalign` API used below. Instead we use + // `memalign`, but this unfortunately has the property on some systems + // where the memory returned cannot be deallocated by `free`! + // + // Upon closer inspection, however, this appears to work just fine with + // Android, so for this platform we should be fine to call `memalign` + // (which is present in API level 9). Some helpful references could + // possibly be chromium using memalign [1], attempts at documenting that + // memalign + free is ok [2] [3], or the current source of chromium + // which still uses memalign on android [4]. + // + // [1]: https://codereview.chromium.org/10796020/ + // [2]: https://code.google.com/p/android/issues/detail?id=35391 + // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 + // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ + // /memory/aligned_memory.cc + libc::memalign(align, size) as *mut u8 + } + + #[cfg(not(any(target_os = "android", target_os = "redox")))] + #[inline] + unsafe fn aligned_malloc(size: usize, align: usize) -> *mut u8 { + let mut out = ptr::null_mut(); + let ret = libc::posix_memalign(&mut out, align, size); + if ret != 0 { + ptr::null_mut() + } else { + out as *mut u8 + } + } +} + +#[cfg(windows)] +#[allow(bad_style)] +mod platform { + + use super::MIN_ALIGN; + type LPVOID = *mut u8; + type HANDLE = LPVOID; + type SIZE_T = usize; + type DWORD = u32; + type BOOL = i32; + + + extern "system" { + fn GetProcessHeap() -> HANDLE; + fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; + fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; + fn GetLastError() -> DWORD; + } + + #[repr(C)] + struct Header(*mut u8); + + unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { + &mut *(ptr as *mut Header).offset(-1) + } + + unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { + let aligned = ptr.offset((align - (ptr as usize & (align - 1))) as isize); + *get_header(aligned) = Header(ptr); + aligned + } + + #[inline] + unsafe fn allocate_with_flags(size: usize, align: usize, flags: DWORD) -> *mut u8 + { + if align <= MIN_ALIGN { + HeapAlloc(GetProcessHeap(), flags, size) + } else { + let size = size + align; + let ptr = HeapAlloc(GetProcessHeap(), flags, size); + if ptr.is_null() { + ptr + } else { + align_ptr(ptr, align) + } + } + } + + #[inline] + pub unsafe fn alloc(size: usize, align: usize) -> *mut u8 { + allocate_with_flags(size, align, 0) + } + + #[inline] + pub unsafe fn dealloc(ptr: *mut u8, align: usize) { + if align <= MIN_ALIGN { + let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); + } else { + let header = get_header(ptr); + let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 23340a713ce..4e1199d4558 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,16 @@ + #![feature(allocator_api)] #![feature(alloc)] extern crate alloc; - pub use std::*; mod bench; mod table; mod shim; +#[path="alloc.rs"] +mod alloc2; pub mod hash_map; pub mod hash_set;