Skip to content

Commit e3b414d

Browse files
committed
std: Stop prefixing jemalloc symbols
Now that we properly only link in jemalloc when building executables, we have far less to worry about in terms of polluting the global namespace with the `free` and `malloc` symbols on Linux. This commit will primarily allow LLVM to use jemalloc so the compiler will only be using one allocator overall. Locally this took compile time for libsyntax from 95 seconds to 89 (a 6% improvement).
1 parent cc719d2 commit e3b414d

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

mk/rt.mk

+10-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,15 @@ ifeq ($$(CFG_WINDOWSY_$(1)),1)
148148
else ifeq ($(OSTYPE_$(1)), apple-ios)
149149
JEMALLOC_ARGS_$(1) := --disable-tls
150150
else ifeq ($(findstring android, $(OSTYPE_$(1))), android)
151-
JEMALLOC_ARGS_$(1) := --disable-tls
151+
# We force android to have prefixed symbols because apparently replacement of
152+
# the libc allocator doesn't quite work. When this was tested (unprefixed
153+
# symbols), it was found that the `realpath` function in libc would allocate
154+
# with libc malloc (not jemalloc malloc), and then the standard library would
155+
# free with jemalloc free, causing a segfault.
156+
#
157+
# If the test suite passes, however, without symbol prefixes then we should be
158+
# good to go!
159+
JEMALLOC_ARGS_$(1) := --disable-tls --with-jemalloc-prefix=je_
152160
endif
153161

154162
ifdef CFG_ENABLE_DEBUG_JEMALLOC
@@ -186,7 +194,7 @@ JEMALLOC_LOCAL_$(1) := $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1
186194
$$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
187195
@$$(call E, make: jemalloc)
188196
cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
189-
$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \
197+
$$(JEMALLOC_ARGS_$(1)) $(CFG_JEMALLOC_FLAGS) \
190198
--build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \
191199
CC="$$(CC_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1))" \
192200
AR="$$(AR_$(1))" \

src/liballoc_jemalloc/build.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn main() {
5050
.env("AR", &ar)
5151
.env("RANLIB", format!("{} s", ar.display()));
5252

53-
if target.contains("windows-gnu") {
53+
if target.contains("windows") {
5454
// A bit of history here, this used to be --enable-lazy-lock added in
5555
// #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
5656
// was also reported to MinGW:
@@ -72,7 +72,19 @@ fn main() {
7272
// locking, but requires passing an option due to a historical
7373
// default with jemalloc.
7474
cmd.arg("--disable-lazy-lock");
75-
} else if target.contains("ios") || target.contains("android") {
75+
} else if target.contains("ios") {
76+
cmd.arg("--disable-tls");
77+
} else if target.contains("android") {
78+
// We force android to have prefixed symbols because apparently
79+
// replacement of the libc allocator doesn't quite work. When this was
80+
// tested (unprefixed symbols), it was found that the `realpath`
81+
// function in libc would allocate with libc malloc (not jemalloc
82+
// malloc), and then the standard library would free with jemalloc free,
83+
// causing a segfault.
84+
//
85+
// If the test suite passes, however, without symbol prefixes then we
86+
// should be good to go!
87+
cmd.arg("--with-jemalloc-prefix=je_");
7688
cmd.arg("--disable-tls");
7789
}
7890

@@ -82,7 +94,6 @@ fn main() {
8294

8395
// Turn off broken quarantine (see jemalloc/jemalloc#161)
8496
cmd.arg("--disable-fill");
85-
cmd.arg("--with-jemalloc-prefix=je_");
8697
cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
8798
cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
8899

src/liballoc_jemalloc/lib.rs

+23-10
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,25 @@ use libc::{c_int, c_void, size_t};
4141
#[cfg(not(cargobuild))]
4242
extern {}
4343

44+
// Note that the symbols here are prefixed by default on OSX (we don't
45+
// explicitly request it), and on Android we explicitly request it as
46+
// unprefixing cause segfaults (mismatches in allocators).
4447
extern {
45-
fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
46-
fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
47-
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
48-
fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
49-
fn je_nallocx(size: size_t, flags: c_int) -> size_t;
48+
#[cfg_attr(any(target_os = "macos", target_os = "android"),
49+
link_name = "je_mallocx")]
50+
fn mallocx(size: size_t, flags: c_int) -> *mut c_void;
51+
#[cfg_attr(any(target_os = "macos", target_os = "android"),
52+
link_name = "je_rallocx")]
53+
fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
54+
#[cfg_attr(any(target_os = "macos", target_os = "android"),
55+
link_name = "je_xallocx")]
56+
fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
57+
#[cfg_attr(any(target_os = "macos", target_os = "android"),
58+
link_name = "je_sdallocx")]
59+
fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
60+
#[cfg_attr(any(target_os = "macos", target_os = "android"),
61+
link_name = "je_nallocx")]
62+
fn nallocx(size: size_t, flags: c_int) -> size_t;
5063
}
5164

5265
// The minimum alignment guaranteed by the architecture. This value is used to
@@ -78,7 +91,7 @@ fn align_to_flags(align: usize) -> c_int {
7891
#[no_mangle]
7992
pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
8093
let flags = align_to_flags(align);
81-
unsafe { je_mallocx(size as size_t, flags) as *mut u8 }
94+
unsafe { mallocx(size as size_t, flags) as *mut u8 }
8295
}
8396

8497
#[no_mangle]
@@ -88,7 +101,7 @@ pub extern "C" fn __rust_reallocate(ptr: *mut u8,
88101
align: usize)
89102
-> *mut u8 {
90103
let flags = align_to_flags(align);
91-
unsafe { je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 }
104+
unsafe { rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 }
92105
}
93106

94107
#[no_mangle]
@@ -98,19 +111,19 @@ pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
98111
align: usize)
99112
-> usize {
100113
let flags = align_to_flags(align);
101-
unsafe { je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize }
114+
unsafe { xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize }
102115
}
103116

104117
#[no_mangle]
105118
pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
106119
let flags = align_to_flags(align);
107-
unsafe { je_sdallocx(ptr as *mut c_void, old_size as size_t, flags) }
120+
unsafe { sdallocx(ptr as *mut c_void, old_size as size_t, flags) }
108121
}
109122

110123
#[no_mangle]
111124
pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
112125
let flags = align_to_flags(align);
113-
unsafe { je_nallocx(size as size_t, flags) as usize }
126+
unsafe { nallocx(size as size_t, flags) as usize }
114127
}
115128

116129
// These symbols are used by jemalloc on android but the really old android

0 commit comments

Comments
 (0)