Skip to content

Commit a888333

Browse files
committed
Auto merge of #31460 - alexcrichton:supafast-rustc, r=brson
Looking at some profiles of rustc recently, these seemed like two pretty easy wins we could get in terms of performance on the table.
2 parents 9b367d9 + e3b414d commit a888333

File tree

11 files changed

+160
-16
lines changed

11 files changed

+160
-16
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

src/librustc_data_structures/fnv.rs

+4
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
3535
pub struct FnvHasher(u64);
3636

3737
impl Default for FnvHasher {
38+
#[inline]
3839
fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
3940
}
4041

4142
impl Hasher for FnvHasher {
43+
#[inline]
4244
fn write(&mut self, bytes: &[u8]) {
4345
let FnvHasher(mut hash) = *self;
4446
for byte in bytes {
@@ -47,5 +49,7 @@ impl Hasher for FnvHasher {
4749
}
4850
*self = FnvHasher(hash);
4951
}
52+
53+
#[inline]
5054
fn finish(&self) -> u64 { self.0 }
5155
}

src/librustc_trans/back/link.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1253,7 +1253,11 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session,
12531253

12541254
if any_objects {
12551255
archive.build();
1256-
cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
1256+
if dylib {
1257+
cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
1258+
} else {
1259+
cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst));
1260+
}
12571261
}
12581262
});
12591263
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
# file at the top-level directory of this distribution and at
3+
# http://rust-lang.org/COPYRIGHT.
4+
#
5+
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
# option. This file may not be copied, modified, or distributed
9+
# except according to those terms.
10+
11+
-include ../tools.mk
12+
13+
all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar)
14+
$(RUSTC) lib1.rs
15+
$(RUSTC) lib2.rs
16+
$(RUSTC) main.rs -Clto
17+
$(call RUN,main)
18+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
int foo() {
12+
return 2;
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
int foo() {
12+
return 1;
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "rlib"]
12+
13+
#[link(name = "foo", kind = "static")]
14+
extern {
15+
fn foo() -> i32;
16+
}
17+
18+
pub fn foo1() -> i32 {
19+
unsafe { foo() }
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![crate_type = "rlib"]
12+
13+
extern crate lib1;
14+
15+
#[link(name = "bar", kind = "static")]
16+
extern {
17+
fn foo() -> i32;
18+
}
19+
20+
pub fn foo2() -> i32 {
21+
unsafe { foo() }
22+
}
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
extern crate lib1;
12+
extern crate lib2;
13+
14+
fn main() {
15+
assert_eq!(lib1::foo1(), 2);
16+
assert_eq!(lib2::foo2(), 2);
17+
}

0 commit comments

Comments
 (0)