summaryrefslogtreecommitdiffstats
path: root/vendor/dlmalloc/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vendor/dlmalloc/src/lib.rs170
1 files changed, 170 insertions, 0 deletions
diff --git a/vendor/dlmalloc/src/lib.rs b/vendor/dlmalloc/src/lib.rs
new file mode 100644
index 000000000..238386fbc
--- /dev/null
+++ b/vendor/dlmalloc/src/lib.rs
@@ -0,0 +1,170 @@
+//! A Rust port of the `dlmalloc` allocator.
+//!
+//! The `dlmalloc` allocator is described at
+//! http://g.oswego.edu/dl/html/malloc.html and this Rust crate is a straight
+//! port of the C code for the allocator into Rust. The implementation is
+//! wrapped up in a `Dlmalloc` type and has support for Linux, OSX, and Wasm
+//! currently.
+//!
+//! The primary purpose of this crate is that it serves as the default memory
+//! allocator for the `wasm32-unknown-unknown` target in the standard library.
+//! Support for other platforms is largely untested and unused, but is used when
+//! testing this crate.
+
+#![allow(dead_code)]
+#![no_std]
+#![deny(missing_docs)]
+#![cfg_attr(target_arch = "wasm64", feature(simd_wasm64))]
+
+use core::cmp;
+use core::ptr;
+use sys::System;
+
+#[cfg(feature = "global")]
+pub use self::global::{enable_alloc_after_fork, GlobalDlmalloc};
+
+mod dlmalloc;
+#[cfg(feature = "global")]
+mod global;
+
+/// In order for this crate to efficiently manage memory, it needs a way to communicate with the
+/// underlying platform. This `Allocator` trait provides an interface for this communication.
+pub unsafe trait Allocator: Send {
+ /// Allocates system memory region of at least `size` bytes
+ /// Returns a triple of `(base, size, flags)` where `base` is a pointer to the beginning of the
+ /// allocated memory region. `size` is the actual size of the region while `flags` specifies
+ /// properties of the allocated region. If `EXTERN_BIT` (bit 0) set in flags, then we did not
+ /// allocate this segment and so should not try to deallocate or merge with others.
+ /// This function can return a `std::ptr::null_mut()` when allocation fails (other values of
+ /// the triple will be ignored).
+ fn alloc(&self, size: usize) -> (*mut u8, usize, u32);
+
+ /// Remaps system memory region at `ptr` with size `oldsize` to a potential new location with
+ /// size `newsize`. `can_move` indicates if the location is allowed to move to a completely new
+ /// location, or that it is only allowed to change in size. Returns a pointer to the new
+ /// location in memory.
+ /// This function can return a `std::ptr::null_mut()` to signal an error.
+ fn remap(&self, ptr: *mut u8, oldsize: usize, newsize: usize, can_move: bool) -> *mut u8;
+
+ /// Frees a part of a memory chunk. The original memory chunk starts at `ptr` with size `oldsize`
+ /// and is turned into a memory region starting at the same address but with `newsize` bytes.
+ /// Returns `true` iff the access memory region could be freed.
+ fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool;
+
+ /// Frees an entire memory region. Returns `true` iff the operation succeeded. When `false` is
+ /// returned, the `dlmalloc` may re-use the location on future allocation requests
+ fn free(&self, ptr: *mut u8, size: usize) -> bool;
+
+ /// Indicates if the system can release a part of memory. For the `flags` argument, see
+ /// `Allocator::alloc`
+ fn can_release_part(&self, flags: u32) -> bool;
+
+ /// Indicates whether newly allocated regions contain zeros.
+ fn allocates_zeros(&self) -> bool;
+
+ /// Returns the page size. Must be a power of two
+ fn page_size(&self) -> usize;
+}
+
+/// An allocator instance
+///
+/// Instances of this type are used to allocate blocks of memory. For best
+/// results only use one of these. Currently doesn't implement `Drop` to release
+/// lingering memory back to the OS. That may happen eventually though!
+pub struct Dlmalloc<A = System>(dlmalloc::Dlmalloc<A>);
+
+#[cfg(target_family = "wasm")]
+#[path = "wasm.rs"]
+mod sys;
+
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+#[path = "unix.rs"]
+mod sys;
+
+#[cfg(not(any(target_os = "linux", target_os = "macos", target_family = "wasm")))]
+#[path = "dummy.rs"]
+mod sys;
+
+impl Dlmalloc<System> {
+ /// Creates a new instance of an allocator
+ pub const fn new() -> Dlmalloc<System> {
+ Dlmalloc(dlmalloc::Dlmalloc::new(System::new()))
+ }
+}
+
+impl<A> Dlmalloc<A> {
+ /// Creates a new instance of an allocator
+ pub const fn new_with_allocator(sys_allocator: A) -> Dlmalloc<A> {
+ Dlmalloc(dlmalloc::Dlmalloc::new(sys_allocator))
+ }
+}
+
+impl<A: Allocator> Dlmalloc<A> {
+ /// Allocates `size` bytes with `align` align.
+ ///
+ /// Returns a null pointer if allocation fails. Returns a valid pointer
+ /// otherwise.
+ ///
+ /// Safety and contracts are largely governed by the `GlobalAlloc::alloc`
+ /// method contracts.
+ #[inline]
+ pub unsafe fn malloc(&mut self, size: usize, align: usize) -> *mut u8 {
+ if align <= self.0.malloc_alignment() {
+ self.0.malloc(size)
+ } else {
+ self.0.memalign(align, size)
+ }
+ }
+
+ /// Same as `malloc`, except if the allocation succeeds it's guaranteed to
+ /// point to `size` bytes of zeros.
+ #[inline]
+ pub unsafe fn calloc(&mut self, size: usize, align: usize) -> *mut u8 {
+ let ptr = self.malloc(size, align);
+ if !ptr.is_null() && self.0.calloc_must_clear(ptr) {
+ ptr::write_bytes(ptr, 0, size);
+ }
+ ptr
+ }
+
+ /// Deallocates a `ptr` with `size` and `align` as the previous request used
+ /// to allocate it.
+ ///
+ /// Safety and contracts are largely governed by the `GlobalAlloc::dealloc`
+ /// method contracts.
+ #[inline]
+ pub unsafe fn free(&mut self, ptr: *mut u8, size: usize, align: usize) {
+ drop((size, align));
+ self.0.free(ptr)
+ }
+
+ /// Reallocates `ptr`, a previous allocation with `old_size` and
+ /// `old_align`, to have `new_size` and the same alignment as before.
+ ///
+ /// Returns a null pointer if the memory couldn't be reallocated, but `ptr`
+ /// is still valid. Returns a valid pointer and frees `ptr` if the request
+ /// is satisfied.
+ ///
+ /// Safety and contracts are largely governed by the `GlobalAlloc::realloc`
+ /// method contracts.
+ #[inline]
+ pub unsafe fn realloc(
+ &mut self,
+ ptr: *mut u8,
+ old_size: usize,
+ old_align: usize,
+ new_size: usize,
+ ) -> *mut u8 {
+ if old_align <= self.0.malloc_alignment() {
+ self.0.realloc(ptr, new_size)
+ } else {
+ let res = self.malloc(new_size, old_align);
+ if !res.is_null() {
+ let size = cmp::min(old_size, new_size);
+ ptr::copy_nonoverlapping(ptr, res, size);
+ self.free(ptr, old_size, old_align);
+ }
+ res
+ }
+ }
+}