Skip to content

Commit 4cd932f

Browse files
committed
alloc: Allow disabling jemalloc
1 parent 7613c9d commit 4cd932f

File tree

4 files changed

+208
-48
lines changed

4 files changed

+208
-48
lines changed

configure

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
421421
opt rpath 1 "build rpaths into rustc itself"
422422
opt nightly 0 "build nightly packages"
423423
opt verify-install 1 "verify installed binaries work"
424+
opt jemalloc 1 "build liballoc with jemalloc"
424425
valopt prefix "/usr/local" "set installation prefix"
425426
valopt local-rust-root "/usr/local" "set prefix for local rust binary"
426427
valopt llvm-root "" "set LLVM root"
@@ -1167,6 +1168,7 @@ putvar CFG_MANDIR
11671168
putvar CFG_DISABLE_INJECT_STD_VERSION
11681169
putvar CFG_JEMALLOC_ROOT
11691170
putvar CFG_LIBUV_ROOT
1171+
putvar CFG_DISABLE_JEMALLOC
11701172

11711173
# Avoid spurious warnings from clang by feeding it original source on
11721174
# ccache-miss rather than preprocessed input.

mk/rt.mk

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,8 @@ $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
306306
EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1)) -g1"
307307
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
308308

309+
ifeq ($$(CFG_DISABLE_JEMALLOC),)
310+
RUSTFLAGS_alloc := --cfg jemalloc
309311
ifeq ($(1),$$(CFG_BUILD))
310312
ifneq ($$(CFG_JEMALLOC_ROOT),)
311313
$$(JEMALLOC_LIB_$(1)): $$(CFG_JEMALLOC_ROOT)/libjemalloc_pic.a
@@ -319,6 +321,10 @@ else
319321
$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_LOCAL_$(1))
320322
$$(Q)cp $$< $$@
321323
endif
324+
else
325+
$$(JEMALLOC_LIB_$(1)): $$(MKFILE_DEPS)
326+
$$(Q)touch $$@
327+
endif
322328

323329
################################################################################
324330
# compiler-rt

mk/target.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
8484
-L "$$(RT_OUTPUT_DIR_$(2))" \
8585
-L "$$(LLVM_LIBDIR_$(2))" \
8686
-L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \
87+
$$(RUSTFLAGS_$(4)) \
8788
--out-dir $$(@D) $$<
8889
@touch $$@
8990
$$(call LIST_ALL_OLD_GLOB_MATCHES,\

src/liballoc/heap.rs

Lines changed: 199 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,48 +12,17 @@
1212
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
1313
// and `nonnull`
1414

15-
use core::intrinsics::{abort, cttz32};
16-
use core::option::{None, Option};
17-
use core::ptr::{RawPtr, mut_null, null};
18-
use libc::{c_char, c_int, c_void, size_t};
19-
2015
#[cfg(not(test))] use core::raw;
2116
#[cfg(not(test))] use util;
2217

23-
#[link(name = "jemalloc", kind = "static")]
24-
extern {
25-
fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
26-
fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
27-
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
28-
flags: c_int) -> size_t;
29-
fn je_dallocx(ptr: *mut c_void, flags: c_int);
30-
fn je_nallocx(size: size_t, flags: c_int) -> size_t;
31-
fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void, *c_char)>,
32-
cbopaque: *mut c_void,
33-
opts: *c_char);
34-
}
35-
36-
// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
37-
#[cfg(not(windows), not(target_os = "android"))]
38-
#[link(name = "pthread")]
39-
extern {}
40-
41-
// MALLOCX_ALIGN(a) macro
42-
#[inline(always)]
43-
fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }
44-
4518
/// Return a pointer to `size` bytes of memory.
4619
///
4720
/// Behavior is undefined if the requested size is 0 or the alignment is not a
4821
/// power of 2. The alignment must be no larger than the largest supported page
4922
/// size on the platform.
5023
#[inline]
5124
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
52-
let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
53-
if ptr.is_null() {
54-
abort()
55-
}
56-
ptr
25+
imp::allocate(size, align)
5726
}
5827

5928
/// 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 {
6736
/// create the allocation referenced by `ptr`. The `old_size` parameter may also
6837
/// be the value returned by `usable_size` for the requested size.
6938
#[inline]
70-
#[allow(unused_variable)] // for the parameter names in the documentation
7139
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
7240
old_size: uint) -> *mut u8 {
73-
let ptr = je_rallocx(ptr as *mut c_void, size as size_t,
74-
mallocx_align(align)) as *mut u8;
75-
if ptr.is_null() {
76-
abort()
77-
}
78-
ptr
41+
imp::reallocate(ptr, size, align, old_size)
7942
}
8043

8144
/// 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,
9255
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
9356
/// any value in range_inclusive(requested_size, usable_size).
9457
#[inline]
95-
#[allow(unused_variable)] // for the parameter names in the documentation
9658
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
9759
old_size: uint) -> bool {
98-
je_xallocx(ptr as *mut c_void, size as size_t, 0,
99-
mallocx_align(align)) == size as size_t
60+
imp::reallocate_inplace(ptr, size, align, old_size)
10061
}
10162

10263
/// Deallocate the memory referenced by `ptr`.
@@ -107,16 +68,15 @@ pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
10768
/// create the allocation referenced by `ptr`. The `size` parameter may also be
10869
/// the value returned by `usable_size` for the requested size.
10970
#[inline]
110-
#[allow(unused_variable)] // for the parameter names in the documentation
11171
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
112-
je_dallocx(ptr as *mut c_void, mallocx_align(align))
72+
imp::deallocate(ptr, size, align)
11373
}
11474

11575
/// Return the usable size of an allocation created with the specified the
11676
/// `size` and `align`.
11777
#[inline]
11878
pub fn usable_size(size: uint, align: uint) -> uint {
119-
unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
79+
imp::usable_size(size, align)
12080
}
12181

12282
/// Print implementation-defined allocator statistics.
@@ -125,9 +85,7 @@ pub fn usable_size(size: uint, align: uint) -> uint {
12585
/// during the call.
12686
#[unstable]
12787
pub fn stats_print() {
128-
unsafe {
129-
je_malloc_stats_print(None, mut_null(), null())
130-
}
88+
imp::stats_print();
13189
}
13290

13391
// 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,
170128
alloc as *mut u8
171129
}
172130

131+
#[cfg(jemalloc)]
132+
mod imp {
133+
use core::intrinsics::abort;
134+
use core::option::{None, Option};
135+
use core::ptr::{RawPtr, mut_null, null};
136+
use core::num::Bitwise;
137+
use libc::{c_char, c_int, c_void, size_t};
138+
139+
#[link(name = "jemalloc", kind = "static")]
140+
extern {
141+
fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
142+
fn je_rallocx(ptr: *mut c_void, size: size_t,
143+
flags: c_int) -> *mut c_void;
144+
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
145+
flags: c_int) -> size_t;
146+
fn je_dallocx(ptr: *mut c_void, flags: c_int);
147+
fn je_nallocx(size: size_t, flags: c_int) -> size_t;
148+
fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void, *c_char)>,
149+
cbopaque: *mut c_void,
150+
opts: *c_char);
151+
}
152+
153+
// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
154+
#[cfg(not(windows), not(target_os = "android"))]
155+
#[link(name = "pthread")]
156+
extern {}
157+
158+
// MALLOCX_ALIGN(a) macro
159+
#[inline(always)]
160+
fn mallocx_align(a: uint) -> c_int { a.trailing_zeros() as c_int }
161+
162+
#[inline]
163+
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
164+
let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
165+
if ptr.is_null() {
166+
abort()
167+
}
168+
ptr
169+
}
170+
171+
#[inline]
172+
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
173+
_old_size: uint) -> *mut u8 {
174+
let ptr = je_rallocx(ptr as *mut c_void, size as size_t,
175+
mallocx_align(align)) as *mut u8;
176+
if ptr.is_null() {
177+
abort()
178+
}
179+
ptr
180+
}
181+
182+
#[inline]
183+
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint,
184+
_old_size: uint) -> bool {
185+
je_xallocx(ptr as *mut c_void, size as size_t, 0,
186+
mallocx_align(align)) == size as size_t
187+
}
188+
189+
#[inline]
190+
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, align: uint) {
191+
je_dallocx(ptr as *mut c_void, mallocx_align(align))
192+
}
193+
194+
#[inline]
195+
pub fn usable_size(size: uint, align: uint) -> uint {
196+
unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
197+
}
198+
199+
pub fn stats_print() {
200+
unsafe {
201+
je_malloc_stats_print(None, mut_null(), null())
202+
}
203+
}
204+
}
205+
206+
#[cfg(not(jemalloc), unix)]
207+
mod imp {
208+
use core::mem;
209+
use core::ptr;
210+
use libc;
211+
use libc_heap;
212+
213+
extern {
214+
fn posix_memalign(memptr: *mut *mut libc::c_void,
215+
align: libc::size_t,
216+
size: libc::size_t) -> libc::c_int;
217+
}
218+
219+
#[inline]
220+
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
221+
// The posix_memalign manpage states
222+
//
223+
// alignment [...] must be a power of and a multiple of
224+
// sizeof(void *)
225+
//
226+
// The `align` parameter to this function is the *minimum* alignment for
227+
// a block of memory, so we special case everything under `*uint` to
228+
// just pass it to malloc, which is guaranteed to align to at least the
229+
// size of `*uint`.
230+
if align < mem::size_of::<*uint>() {
231+
libc_heap::malloc_raw(size)
232+
} else {
233+
let mut out = 0 as *mut libc::c_void;
234+
let ret = posix_memalign(&mut out,
235+
align as libc::size_t,
236+
size as libc::size_t);
237+
if ret != 0 {
238+
::oom();
239+
}
240+
out as *mut u8
241+
}
242+
}
243+
244+
#[inline]
245+
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
246+
old_size: uint) -> *mut u8 {
247+
let new_ptr = allocate(size, align);
248+
ptr::copy_memory(new_ptr, ptr as *u8, old_size);
249+
deallocate(ptr, old_size, align);
250+
return new_ptr;
251+
}
252+
253+
#[inline]
254+
pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
255+
_old_size: uint) -> bool {
256+
false
257+
}
258+
259+
#[inline]
260+
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
261+
libc::free(ptr as *mut libc::c_void)
262+
}
263+
264+
#[inline]
265+
pub fn usable_size(size: uint, _align: uint) -> uint {
266+
size
267+
}
268+
269+
pub fn stats_print() {
270+
}
271+
}
272+
273+
#[cfg(not(jemalloc), windows)]
274+
mod imp {
275+
use libc::{c_void, size_t};
276+
use core::ptr::RawPtr;
277+
278+
extern {
279+
fn _aligned_malloc(size: size_t, align: size_t) -> *mut c_void;
280+
fn _aligned_realloc(block: *mut c_void, size: size_t,
281+
align: size_t) -> *mut c_void;
282+
fn _aligned_free(ptr: *mut c_void);
283+
}
284+
285+
#[inline]
286+
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
287+
let ptr = _aligned_malloc(size as size_t, align as size_t);
288+
if ptr.is_null() {
289+
::oom();
290+
}
291+
ptr as *mut u8
292+
}
293+
294+
#[inline]
295+
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint,
296+
_old_size: uint) -> *mut u8 {
297+
let ptr = _aligned_realloc(ptr as *mut c_void, size as size_t,
298+
align as size_t);
299+
if ptr.is_null() {
300+
::oom();
301+
}
302+
ptr as *mut u8
303+
}
304+
305+
#[inline]
306+
pub unsafe fn reallocate_inplace(_ptr: *mut u8, _size: uint, _align: uint,
307+
_old_size: uint) -> bool {
308+
false
309+
}
310+
311+
#[inline]
312+
pub unsafe fn deallocate(ptr: *mut u8, _size: uint, _align: uint) {
313+
_aligned_free(ptr as *mut c_void)
314+
}
315+
316+
#[inline]
317+
pub fn usable_size(size: uint, _align: uint) -> uint {
318+
size
319+
}
320+
321+
pub fn stats_print() {}
322+
}
323+
173324
#[cfg(test)]
174325
mod bench {
175326
extern crate test;

0 commit comments

Comments
 (0)