From 45bf1ed1a1123122ded05ae2eedaf0f190e52726 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 25 Jun 2015 10:07:01 -0700 Subject: rustc: Allow changing the default allocator This commit is an implementation of [RFC 1183][rfc] which allows swapping out the default allocator on nightly Rust. No new stable surface area should be added as a part of this commit. [rfc]: https://github.com/rust-lang/rfcs/pull/1183 Two new attributes have been added to the compiler: * `#![needs_allocator]` - this is used by liballoc (and likely only liballoc) to indicate that it requires an allocator crate to be in scope. * `#![allocator]` - this is a indicator that the crate is an allocator which can satisfy the `needs_allocator` attribute above. The ABI of the allocator crate is defined to be a set of symbols that implement the standard Rust allocation/deallocation functions. The symbols are not currently checked for exhaustiveness or typechecked. There are also a number of restrictions on these crates: * An allocator crate cannot transitively depend on a crate that is flagged as needing an allocator (e.g. allocator crates can't depend on liballoc). * There can only be one explicitly linked allocator in a final image. * If no allocator is explicitly requested one will be injected on behalf of the compiler. Binaries and Rust dylibs will use jemalloc by default where available and staticlibs/other dylibs will use the system allocator by default. Two allocators are provided by the distribution by default, `alloc_system` and `alloc_jemalloc` which operate as advertised. Closes #27389 --- src/liballoc_jemalloc/lib.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/liballoc_jemalloc/lib.rs (limited to 'src/liballoc_jemalloc') diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs new file mode 100644 index 00000000000..2a30f88df49 --- /dev/null +++ b/src/liballoc_jemalloc/lib.rs @@ -0,0 +1,96 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![cfg_attr(stage0, feature(custom_attribute))] +#![crate_name = "alloc_jemalloc"] +#![crate_type = "rlib"] +#![staged_api] +#![no_std] +#![cfg_attr(not(stage0), allocator)] +#![unstable(feature = "alloc_jemalloc", + reason = "this library is unlikely to be stabilized in its current \ + form or name")] +#![feature(allocator)] +#![feature(libc)] +#![feature(no_std)] +#![feature(staged_api)] + +extern crate libc; + +use libc::{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_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); + fn je_nallocx(size: size_t, flags: c_int) -> size_t; +} + +// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough +#[cfg(all(not(windows), + not(target_os = "android"), + not(target_env = "musl")))] +#[link(name = "pthread")] +extern {} + +// 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 = "arm", + target_arch = "mips", + target_arch = "mipsel", + target_arch = "powerpc")))] +const MIN_ALIGN: usize = 8; +#[cfg(all(any(target_arch = "x86", + target_arch = "x86_64", + target_arch = "aarch64")))] +const MIN_ALIGN: usize = 16; + +// MALLOCX_ALIGN(a) macro +fn mallocx_align(a: usize) -> c_int { a.trailing_zeros() as c_int } + +fn align_to_flags(align: usize) -> c_int { + if align <= MIN_ALIGN { 0 } else { mallocx_align(align) } +} + +#[no_mangle] +pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 { + let flags = align_to_flags(align); + unsafe { je_mallocx(size as size_t, flags) as *mut u8 } +} + +#[no_mangle] +pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize, + align: usize) -> *mut u8 { + let flags = align_to_flags(align); + unsafe { je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 } +} + +#[no_mangle] +pub extern fn __rust_reallocate_inplace(ptr: *mut u8, _old_size: usize, + size: usize, align: usize) -> usize { + let flags = align_to_flags(align); + unsafe { je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize } +} + +#[no_mangle] +pub extern fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { + let flags = align_to_flags(align); + unsafe { je_sdallocx(ptr as *mut c_void, old_size as size_t, flags) } +} + +#[no_mangle] +pub extern fn __rust_usable_size(size: usize, align: usize) -> usize { + let flags = align_to_flags(align); + unsafe { je_nallocx(size as size_t, flags) as usize } +} -- cgit 1.4.1-3-g733a5