alloc: Allow disabling jemalloc
This commit is contained in:
parent
7613c9dd59
commit
4cd932f94e
2
configure
vendored
2
configure
vendored
@ -421,6 +421,7 @@ opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
|
|||||||
opt rpath 1 "build rpaths into rustc itself"
|
opt rpath 1 "build rpaths into rustc itself"
|
||||||
opt nightly 0 "build nightly packages"
|
opt nightly 0 "build nightly packages"
|
||||||
opt verify-install 1 "verify installed binaries work"
|
opt verify-install 1 "verify installed binaries work"
|
||||||
|
opt jemalloc 1 "build liballoc with jemalloc"
|
||||||
valopt prefix "/usr/local" "set installation prefix"
|
valopt prefix "/usr/local" "set installation prefix"
|
||||||
valopt local-rust-root "/usr/local" "set prefix for local rust binary"
|
valopt local-rust-root "/usr/local" "set prefix for local rust binary"
|
||||||
valopt llvm-root "" "set LLVM root"
|
valopt llvm-root "" "set LLVM root"
|
||||||
@ -1167,6 +1168,7 @@ putvar CFG_MANDIR
|
|||||||
putvar CFG_DISABLE_INJECT_STD_VERSION
|
putvar CFG_DISABLE_INJECT_STD_VERSION
|
||||||
putvar CFG_JEMALLOC_ROOT
|
putvar CFG_JEMALLOC_ROOT
|
||||||
putvar CFG_LIBUV_ROOT
|
putvar CFG_LIBUV_ROOT
|
||||||
|
putvar CFG_DISABLE_JEMALLOC
|
||||||
|
|
||||||
# Avoid spurious warnings from clang by feeding it original source on
|
# Avoid spurious warnings from clang by feeding it original source on
|
||||||
# ccache-miss rather than preprocessed input.
|
# ccache-miss rather than preprocessed input.
|
||||||
|
6
mk/rt.mk
6
mk/rt.mk
@ -306,6 +306,8 @@ $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
|
|||||||
EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1)) -g1"
|
EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1)) -g1"
|
||||||
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
|
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
|
||||||
|
|
||||||
|
ifeq ($$(CFG_DISABLE_JEMALLOC),)
|
||||||
|
RUSTFLAGS_alloc := --cfg jemalloc
|
||||||
ifeq ($(1),$$(CFG_BUILD))
|
ifeq ($(1),$$(CFG_BUILD))
|
||||||
ifneq ($$(CFG_JEMALLOC_ROOT),)
|
ifneq ($$(CFG_JEMALLOC_ROOT),)
|
||||||
$$(JEMALLOC_LIB_$(1)): $$(CFG_JEMALLOC_ROOT)/libjemalloc_pic.a
|
$$(JEMALLOC_LIB_$(1)): $$(CFG_JEMALLOC_ROOT)/libjemalloc_pic.a
|
||||||
@ -319,6 +321,10 @@ else
|
|||||||
$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
|
$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
|
||||||
$$(Q)cp $$< $$@
|
$$(Q)cp $$< $$@
|
||||||
endif
|
endif
|
||||||
|
else
|
||||||
|
$$(JEMALLOC_LIB_$(1)): $$(MKFILE_DEPS)
|
||||||
|
$$(Q)touch $$@
|
||||||
|
endif
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# compiler-rt
|
# compiler-rt
|
||||||
|
@ -84,6 +84,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
|
|||||||
-L "$$(RT_OUTPUT_DIR_$(2))" \
|
-L "$$(RT_OUTPUT_DIR_$(2))" \
|
||||||
-L "$$(LLVM_LIBDIR_$(2))" \
|
-L "$$(LLVM_LIBDIR_$(2))" \
|
||||||
-L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \
|
-L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \
|
||||||
|
$$(RUSTFLAGS_$(4)) \
|
||||||
--out-dir $$(@D) $$<
|
--out-dir $$(@D) $$<
|
||||||
@touch $$@
|
@touch $$@
|
||||||
$$(call LIST_ALL_OLD_GLOB_MATCHES,\
|
$$(call LIST_ALL_OLD_GLOB_MATCHES,\
|
||||||
|
@ -12,36 +12,9 @@
|
|||||||
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
|
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
|
||||||
// and `nonnull`
|
// and `nonnull`
|
||||||
|
|
||||||
use core::intrinsics::{abort, cttz32};
|
|
||||||
use core::option::{None, Option};
|
|
||||||
use core::ptr::{RawPtr, mut_null, null};
|
|
||||||
use libc::{c_char, c_int, c_void, size_t};
|
|
||||||
|
|
||||||
#[cfg(not(test))] use core::raw;
|
#[cfg(not(test))] use core::raw;
|
||||||
#[cfg(not(test))] use util;
|
#[cfg(not(test))] use util;
|
||||||
|
|
||||||
#[link(name = "jemalloc", kind = "static")]
|
|
||||||
extern {
|
|
||||||
fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
|
|
||||||
fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
|
|
||||||
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
|
|
||||||
flags: c_int) -> size_t;
|
|
||||||
fn je_dallocx(ptr: *mut c_void, flags: c_int);
|
|
||||||
fn je_nallocx(size: size_t, flags: c_int) -> size_t;
|
|
||||||
fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void, *c_char)>,
|
|
||||||
cbopaque: *mut c_void,
|
|
||||||
opts: *c_char);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
|
|
||||||
#[cfg(not(windows), not(target_os = "android"))]
|
|
||||||
#[link(name = "pthread")]
|
|
||||||
extern {}
|
|
||||||
|
|
||||||
// MALLOCX_ALIGN(a) macro
|
|
||||||
#[inline(always)]
|
|
||||||
fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }
|
|
||||||
|
|
||||||
/// Return a pointer to `size` bytes of memory.
|
/// Return a pointer to `size` bytes of memory.
|
||||||
///
|
///
|
||||||
/// Behavior is undefined if the requested size is 0 or the alignment is not a
|
/// Behavior is undefined if the requested size is 0 or the alignment is not a
|
||||||
@ -49,11 +22,7 @@ fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }
|
|||||||
/// size on the platform.
|
/// size on the platform.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||||
let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
|
imp::allocate(size, align)
|
||||||
if ptr.is_null() {
|
|
||||||
abort()
|
|
||||||
}
|
|
||||||
ptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
|
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
|
||||||
@ -67,15 +36,9 @@ pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
|||||||
/// create the allocation referenced by `ptr`. The `old_size` parameter may also
|
/// create the allocation referenced by `ptr`. The `old_size` parameter may also
|
||||||
/// be the value returned by `usable_size` for the requested size.
|
/// be the value returned by `usable_size` for the requested size.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variable)] // for the parameter names in the documentation
|
|
||||||
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
|
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
|
||||||
old_size: uint) -> *mut u8 {
|
old_size: uint) -> *mut u8 {
|
||||||
let ptr = je_rallocx(ptr as *mut c_void, size as size_t,
|
imp::reallocate(ptr, size, align, old_size)
|
||||||
mallocx_align(align)) as *mut u8;
|
|
||||||
if ptr.is_null() {
|
|
||||||
abort()
|
|
||||||
}
|
|
||||||
ptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
|
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of
|
||||||
@ -92,11 +55,9 @@ pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
|
|||||||
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
|
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
|
||||||
/// any value in range_inclusive(requested_size, usable_size).
|
/// any value in range_inclusive(requested_size, usable_size).
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variable)] // for the parameter names in the documentation
|
|
||||||
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
|
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
|
||||||
old_size: uint) -> bool {
|
old_size: uint) -> bool {
|
||||||
je_xallocx(ptr as *mut c_void, size as size_t, 0,
|
imp::reallocate_inplace(ptr, size, align, old_size)
|
||||||
mallocx_align(align)) == size as size_t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deallocate the memory referenced by `ptr`.
|
/// Deallocate the memory referenced by `ptr`.
|
||||||
@ -107,16 +68,15 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
|
|||||||
/// create the allocation referenced by `ptr`. The `size` parameter may also be
|
/// create the allocation referenced by `ptr`. The `size` parameter may also be
|
||||||
/// the value returned by `usable_size` for the requested size.
|
/// the value returned by `usable_size` for the requested size.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variable)] // for the parameter names in the documentation
|
|
||||||
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
|
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
|
||||||
je_dallocx(ptr as *mut c_void, mallocx_align(align))
|
imp::deallocate(ptr, size, align)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the usable size of an allocation created with the specified the
|
/// Return the usable size of an allocation created with the specified the
|
||||||
/// `size` and `align`.
|
/// `size` and `align`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn usable_size(size: uint, align: uint) -> uint {
|
pub fn usable_size(size: uint, align: uint) -> uint {
|
||||||
unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
|
imp::usable_size(size, align)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print implementation-defined allocator statistics.
|
/// Print implementation-defined allocator statistics.
|
||||||
@ -125,9 +85,7 @@ pub fn usable_size(size: uint, align: uint) -> uint {
|
|||||||
/// during the call.
|
/// during the call.
|
||||||
#[unstable]
|
#[unstable]
|
||||||
pub fn stats_print() {
|
pub fn stats_print() {
|
||||||
unsafe {
|
imp::stats_print();
|
||||||
je_malloc_stats_print(None, mut_null(), null())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
|
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
|
||||||
@ -170,6 +128,199 @@ unsafe fn closure_exchange_malloc(drop_glue: fn(*mut u8), size: uint,
|
|||||||
alloc as *mut u8
|
alloc as *mut u8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(jemalloc)]
|
||||||
|
mod imp {
|
||||||
|
use core::intrinsics::abort;
|
||||||
|
use core::option::{None, Option};
|
||||||
|
use core::ptr::{RawPtr, mut_null, null};
|
||||||
|
use core::num::Bitwise;
|
||||||
|
use libc::{c_char, c_int, c_void, size_t};
|
||||||
|
|
||||||
|
#[link(name = "jemalloc", kind = "static")]
|
||||||
|
extern {
|
||||||
|
fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
|
||||||
|
fn je_rallocx(ptr: *mut c_void, size: size_t,
|
||||||
|
flags: c_int) -> *mut c_void;
|
||||||
|
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
|
||||||
|
flags: c_int) -> size_t;
|
||||||
|
fn je_dallocx(ptr: *mut c_void, flags: c_int);
|
||||||
|
fn je_nallocx(size: size_t, flags: c_int) -> size_t;
|
||||||
|
fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void, *c_char)>,
|
||||||
|
cbopaque: *mut c_void,
|
||||||
|
opts: *c_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
|
||||||
|
#[cfg(not(windows), not(target_os = "android"))]
|
||||||
|
#[link(name = "pthread")]
|
||||||
|
extern {}
|
||||||
|
|
||||||
|
// MALLOCX_ALIGN(a) macro
|
||||||
|
#[inline(always)]
|
||||||
|
fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||||
|
let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
|
||||||
|
if ptr.is_null() {
|
||||||
|
abort()
|
||||||
|
}
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
|
||||||
|
_old_size: uint) -> *mut u8 {
|
||||||
|
let ptr = je_rallocx(ptr as *mut c_void, size as size_t,
|
||||||
|
mallocx_align(align)) as *mut u8;
|
||||||
|
if ptr.is_null() {
|
||||||
|
abort()
|
||||||
|
}
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
|
||||||
|
_old_size: uint) -> bool {
|
||||||
|
je_xallocx(ptr as *mut c_void, size as size_t, 0,
|
||||||
|
mallocx_align(align)) == size as size_t
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, align: uint) {
|
||||||
|
je_dallocx(ptr as *mut c_void, mallocx_align(align))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn usable_size(size: uint, align: uint) -> uint {
|
||||||
|
unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stats_print() {
|
||||||
|
unsafe {
|
||||||
|
je_malloc_stats_print(None, mut_null(), null())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(jemalloc), unix)]
|
||||||
|
mod imp {
|
||||||
|
use core::mem;
|
||||||
|
use core::ptr;
|
||||||
|
use libc;
|
||||||
|
use libc_heap;
|
||||||
|
|
||||||
|
extern {
|
||||||
|
fn posix_memalign(memptr: *mut *mut libc::c_void,
|
||||||
|
align: libc::size_t,
|
||||||
|
size: libc::size_t) -> libc::c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||||
|
// The posix_memalign manpage states
|
||||||
|
//
|
||||||
|
// alignment [...] must be a power of and a multiple of
|
||||||
|
// sizeof(void *)
|
||||||
|
//
|
||||||
|
// The `align` parameter to this function is the *minimum* alignment for
|
||||||
|
// a block of memory, so we special case everything under `*uint` to
|
||||||
|
// just pass it to malloc, which is guaranteed to align to at least the
|
||||||
|
// size of `*uint`.
|
||||||
|
if align < mem::size_of::<*uint>() {
|
||||||
|
libc_heap::malloc_raw(size)
|
||||||
|
} else {
|
||||||
|
let mut out = 0 as *mut libc::c_void;
|
||||||
|
let ret = posix_memalign(&mut out,
|
||||||
|
align as libc::size_t,
|
||||||
|
size as libc::size_t);
|
||||||
|
if ret != 0 {
|
||||||
|
::oom();
|
||||||
|
}
|
||||||
|
out as *mut u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
|
||||||
|
old_size: uint) -> *mut u8 {
|
||||||
|
let new_ptr = allocate(size, align);
|
||||||
|
ptr::copy_memory(new_ptr, ptr as *u8, old_size);
|
||||||
|
deallocate(ptr, old_size, align);
|
||||||
|
return new_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
|
||||||
|
_old_size: uint) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
|
||||||
|
libc::free(ptr as *mut libc::c_void)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn usable_size(size: uint, _align: uint) -> uint {
|
||||||
|
size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stats_print() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(jemalloc), windows)]
|
||||||
|
mod imp {
|
||||||
|
use libc::{c_void, size_t};
|
||||||
|
use core::ptr::RawPtr;
|
||||||
|
|
||||||
|
extern {
|
||||||
|
fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
|
||||||
|
fn _aligned_realloc(block: *mut c_void, size: size_t,
|
||||||
|
align: size_t) -> *mut c_void;
|
||||||
|
fn _aligned_free(ptr: *mut c_void);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
|
||||||
|
let ptr = _aligned_malloc(size as size_t, align as size_t);
|
||||||
|
if ptr.is_null() {
|
||||||
|
::oom();
|
||||||
|
}
|
||||||
|
ptr as *mut u8
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
|
||||||
|
_old_size: uint) -> *mut u8 {
|
||||||
|
let ptr = _aligned_realloc(ptr as *mut c_void, size as size_t,
|
||||||
|
align as size_t);
|
||||||
|
if ptr.is_null() {
|
||||||
|
::oom();
|
||||||
|
}
|
||||||
|
ptr as *mut u8
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
|
||||||
|
_old_size: uint) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
|
||||||
|
_aligned_free(ptr as *mut c_void)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn usable_size(size: uint, _align: uint) -> uint {
|
||||||
|
size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stats_print() {}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod bench {
|
mod bench {
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
Loading…
Reference in New Issue
Block a user