1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
//! This module exposes a set of malloc API. They are currently implemented with
//! the library malloc. This may change in the future, and will be replaced
//! with a native MMTk implementation.
//! We have two versions for each function:
//! * a normal version: it has the signature that is compatible with the standard malloc library.
//! * a counted version: the allocated/freed bytes are calculated into MMTk's heap. So extra arguments
//! are needed to maintain allocated bytes properly. The API is inspired by Julia's counted malloc.
//! The counted version is only available with the feature `malloc_counted_size`.
/// Malloc provided by libraries
pub(crate) mod library;
/// Using malloc as mark sweep free-list allocator.
pub(crate) mod malloc_ms_util;
use crate::util::Address;
#[cfg(feature = "malloc_counted_size")]
use crate::vm::VMBinding;
#[cfg(feature = "malloc_counted_size")]
use crate::MMTK;
/// Manually allocate memory. Similar to libc's malloc.
pub fn malloc(size: usize) -> Address {
Address::from_mut_ptr(unsafe { self::library::malloc(size) })
}
/// Manually allocate memory. Similar to libc's malloc.
/// This also counts the allocated memory into the heap size of the given MMTk instance.
#[cfg(feature = "malloc_counted_size")]
pub fn counted_malloc<VM: VMBinding>(mmtk: &MMTK<VM>, size: usize) -> Address {
let res = malloc(size);
if !res.is_zero() {
mmtk.state.increase_malloc_bytes_by(size);
}
res
}
/// Manually allocate memory and initialize the bytes in the allocated memory to zero. Similar to libc's calloc.
pub fn calloc(num: usize, size: usize) -> Address {
Address::from_mut_ptr(unsafe { self::library::calloc(num, size) })
}
/// Manually allocate memory and initialize the bytes in the allocated memory to zero. Similar to libc's calloc.
/// This also counts the allocated memory into the heap size of the given MMTk instance.
#[cfg(feature = "malloc_counted_size")]
pub fn counted_calloc<VM: VMBinding>(mmtk: &MMTK<VM>, num: usize, size: usize) -> Address {
let res = calloc(num, size);
if !res.is_zero() {
mmtk.state.increase_malloc_bytes_by(num * size);
}
res
}
/// Reallocate the given area of memory. Similar to libc's realloc.
pub fn realloc(addr: Address, size: usize) -> Address {
Address::from_mut_ptr(unsafe { self::library::realloc(addr.to_mut_ptr(), size) })
}
/// Reallocate the given area of memory. Similar to libc's realloc.
/// This also adjusts the allocated memory size based on the original allocation and the new allocation, and counts
/// that into the heap size for the given MMTk instance.
#[cfg(feature = "malloc_counted_size")]
pub fn realloc_with_old_size<VM: VMBinding>(
mmtk: &MMTK<VM>,
addr: Address,
size: usize,
old_size: usize,
) -> Address {
let res = realloc(addr, size);
if !addr.is_zero() {
mmtk.state.decrease_malloc_bytes_by(old_size);
}
if size != 0 && !res.is_zero() {
mmtk.state.increase_malloc_bytes_by(size);
}
res
}
/// Manually free the memory that is returned from other manual allocation functions in this module.
pub fn free(addr: Address) {
unsafe { self::library::free(addr.to_mut_ptr()) }
}
/// Manually free the memory that is returned from other manual allocation functions in this module.
/// This also reduces the allocated memory size.
#[cfg(feature = "malloc_counted_size")]
pub fn free_with_size<VM: VMBinding>(mmtk: &MMTK<VM>, addr: Address, old_size: usize) {
free(addr);
if !addr.is_zero() {
mmtk.state.decrease_malloc_bytes_by(old_size);
}
}