summaryrefslogtreecommitdiffstats
path: root/servo/components/hashglobe/src/alloc.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /servo/components/hashglobe/src/alloc.rs
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'servo/components/hashglobe/src/alloc.rs')
-rw-r--r--servo/components/hashglobe/src/alloc.rs161
1 files changed, 161 insertions, 0 deletions
diff --git a/servo/components/hashglobe/src/alloc.rs b/servo/components/hashglobe/src/alloc.rs
new file mode 100644
index 0000000000..b1c7a6eca5
--- /dev/null
+++ b/servo/components/hashglobe/src/alloc.rs
@@ -0,0 +1,161 @@
+// FORK NOTE: Copied from liballoc_system, removed unnecessary APIs,
+// APIs take size/align directly instead of Layout
+
+// 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, realloc};
+
+#[cfg(any(unix, target_os = "redox"))]
+mod platform {
+ extern crate libc;
+
+ #[cfg(not(any(target_os = "android")))]
+ 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)
+ }
+
+ #[inline]
+ pub unsafe fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 {
+ libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
+ }
+
+ #[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 HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, 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());
+ }
+ }
+
+ #[inline]
+ pub unsafe fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 {
+ HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, new_size) as *mut u8
+ }
+}