Skip to content

Commit 1b1ca6d

Browse files
committed
add back jemalloc to the tree
This adds a `std::rt::heap` module with a nice allocator API. It's a step towards fixing #13094 and is a starting point for working on a generic allocator trait. The revision used for the jemalloc submodule is the stable 3.6.0 release. Closes #11807
1 parent 11571cd commit 1b1ca6d

File tree

8 files changed

+158
-7
lines changed

8 files changed

+158
-7
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@
1515
[submodule "src/rt/hoedown"]
1616
path = src/rt/hoedown
1717
url = https://github.com/rust-lang/hoedown.git
18+
[submodule "src/jemalloc"]
19+
path = src/jemalloc
20+
url = https://github.com/rust-lang/jemalloc.git

configure

+1
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,7 @@ do
782782
for s in 0 1 2 3
783783
do
784784
make_dir $t/rt/stage$s
785+
make_dir $t/rt/jemalloc
785786
make_dir $t/rt/libuv
786787
make_dir $t/rt/libuv/src/ares
787788
make_dir $t/rt/libuv/src/eio

mk/crates.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ CRATES := $(TARGET_CRATES) $(HOST_CRATES)
5757
TOOLS := compiletest rustdoc rustc
5858

5959
DEPS_core :=
60-
DEPS_std := core libc native:rustrt native:compiler-rt native:backtrace
60+
DEPS_std := core libc native:rustrt native:compiler-rt native:backtrace native:jemalloc
6161
DEPS_green := std rand native:context_switch
6262
DEPS_rustuv := std native:uv native:uv_support
6363
DEPS_native := std

mk/rt.mk

+48-4
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,13 @@ $(foreach lib,$(NATIVE_LIBS), \
122122
################################################################################
123123
# Building third-party targets with external build systems
124124
#
125-
# The only current member of this section is libuv, but long ago this used to
126-
# also be occupied by jemalloc. This location is meant for dependencies which
127-
# have external build systems. It is still assumed that the output of each of
128-
# these steps is a static library in the correct location.
125+
# This location is meant for dependencies which have external build systems. It
126+
# is still assumed that the output of each of these steps is a static library
127+
# in the correct location.
128+
################################################################################
129+
130+
################################################################################
131+
# libuv
129132
################################################################################
130133

131134
define DEF_LIBUV_ARCH_VAR
@@ -154,13 +157,19 @@ define DEF_THIRD_PARTY_TARGETS
154157

155158
ifeq ($$(CFG_WINDOWSY_$(1)), 1)
156159
LIBUV_OSTYPE_$(1) := win
160+
# This isn't necessarily a desired option, but it's harmless and works around
161+
# what appears to be a mingw-w64 bug.
162+
#
163+
# https://sourceforge.net/p/mingw-w64/bugs/395/
164+
JEMALLOC_ARGS_$(1) := --enable-lazy-lock
157165
else ifeq ($(OSTYPE_$(1)), apple-darwin)
158166
LIBUV_OSTYPE_$(1) := mac
159167
else ifeq ($(OSTYPE_$(1)), unknown-freebsd)
160168
LIBUV_OSTYPE_$(1) := freebsd
161169
else ifeq ($(OSTYPE_$(1)), linux-androideabi)
162170
LIBUV_OSTYPE_$(1) := android
163171
LIBUV_ARGS_$(1) := PLATFORM=android host=android OS=linux
172+
JEMALLOC_ARGS_$(1) := --disable-tls
164173
else
165174
LIBUV_OSTYPE_$(1) := linux
166175
endif
@@ -220,6 +229,41 @@ $$(LIBUV_DIR_$(1))/Release/libuv.a: $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) \
220229

221230
endif
222231

232+
################################################################################
233+
# jemalloc
234+
################################################################################
235+
236+
ifdef CFG_ENABLE_FAST_MAKE
237+
JEMALLOC_DEPS := $(S)/.gitmodules
238+
else
239+
JEMALLOC_DEPS := $(wildcard \
240+
$(S)src/jemalloc/* \
241+
$(S)src/jemalloc/*/* \
242+
$(S)src/jemalloc/*/*/* \
243+
$(S)src/jemalloc/*/*/*/*)
244+
endif
245+
246+
JEMALLOC_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc)
247+
ifeq ($$(CFG_WINDOWSY_$(1)),1)
248+
JEMALLOC_REAL_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc_s)
249+
else
250+
JEMALLOC_REAL_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc_pic)
251+
endif
252+
JEMALLOC_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(JEMALLOC_NAME_$(1))
253+
JEMALLOC_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/jemalloc
254+
255+
$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
256+
@$$(call E, make: jemalloc)
257+
cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
258+
$$(JEMALLOC_ARGS_$(1)) --enable-cc-silence --with-jemalloc-prefix=je_ \
259+
--disable-experimental --build=$(CFG_BUILD) --host=$(1) \
260+
CC="$$(CC_$(1))" \
261+
AR="$$(AR_$(1))" \
262+
RANLIB="$$(AR_$(1)) s" \
263+
EXTRA_CFLAGS="$$(CFG_GCCISH_CFLAGS)"
264+
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
265+
$$(Q)cp $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1)) $$(JEMALLOC_LIB_$(1))
266+
223267
################################################################################
224268
# compiler-rt
225269
################################################################################

mk/tests.mk

+3-1
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ ALL_HS := $(filter-out $(S)src/rt/vg/valgrind.h \
240240
tidy:
241241
@$(call E, check: formatting)
242242
$(Q)find $(S)src -name '*.r[sc]' \
243+
| grep '^$(S)src/jemalloc' -v \
243244
| grep '^$(S)src/libuv' -v \
244245
| grep '^$(S)src/llvm' -v \
245246
| grep '^$(S)src/gyp' -v \
@@ -264,8 +265,9 @@ tidy:
264265
$(Q)find $(S)src -type f -perm +111 \
265266
-not -name '*.rs' -and -not -name '*.py' \
266267
-and -not -name '*.sh' \
267-
| grep '^$(S)src/llvm' -v \
268+
| grep '^$(S)src/jemalloc' -v \
268269
| grep '^$(S)src/libuv' -v \
270+
| grep '^$(S)src/llvm' -v \
269271
| grep '^$(S)src/rt/hoedown' -v \
270272
| grep '^$(S)src/gyp' -v \
271273
| grep '^$(S)src/etc' -v \

src/jemalloc

Submodule jemalloc added at 6a96910

src/libstd/rt/heap.rs

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2014 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+
use intrinsics::{abort, cttz32};
12+
use libc::{c_int, c_void, size_t};
13+
use ptr::RawPtr;
14+
15+
#[link(name = "jemalloc", kind = "static")]
16+
extern {
17+
fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
18+
fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
19+
fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
20+
fn je_dallocx(ptr: *mut c_void, flags: c_int);
21+
fn je_nallocx(size: size_t, flags: c_int) -> size_t;
22+
}
23+
24+
// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
25+
#[cfg(not(windows))]
26+
#[link(name = "pthread")]
27+
extern {}
28+
29+
// MALLOCX_ALIGN(a) macro
30+
#[inline(always)]
31+
fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }
32+
33+
/// Return a pointer to `size` bytes of memory.
34+
///
35+
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
36+
/// alignment must be no larger than the largest supported page size on the platform.
37+
#[inline]
38+
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
39+
let ptr = je_mallocx(size as size_t, mallocx_align(align)) as *mut u8;
40+
if ptr.is_null() {
41+
abort()
42+
}
43+
ptr
44+
}
45+
46+
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory.
47+
///
48+
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
49+
/// alignment must be no larger than the largest supported page size on the platform.
50+
///
51+
/// The `old_size` and `align` parameters are the parameters that were used to create the
52+
/// allocation referenced by `ptr`. The `old_size` parameter may also be the value returned by
53+
/// `usable_size` for the requested size.
54+
#[inline]
55+
#[allow(unused_variable)] // for the parameter names in the documentation
56+
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> *mut u8 {
57+
let ptr = je_rallocx(ptr as *mut c_void, size as size_t, mallocx_align(align)) as *mut u8;
58+
if ptr.is_null() {
59+
abort()
60+
}
61+
ptr
62+
}
63+
64+
/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory in-place.
65+
///
66+
/// Return true if successful, otherwise false if the allocation was not altered.
67+
///
68+
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
69+
/// alignment must be no larger than the largest supported page size on the platform.
70+
///
71+
/// The `old_size` and `align` parameters are the parameters that were used to
72+
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
73+
/// any value in range_inclusive(requested_size, usable_size).
74+
#[inline]
75+
#[allow(unused_variable)] // for the parameter names in the documentation
76+
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> bool {
77+
je_xallocx(ptr as *mut c_void, size as size_t, 0, mallocx_align(align)) == size as size_t
78+
}
79+
80+
/// Deallocate the memory referenced by `ptr`.
81+
///
82+
/// The `ptr` parameter must not be null.
83+
///
84+
/// The `size` and `align` parameters are the parameters that were used to create the
85+
/// allocation referenced by `ptr`. The `size` parameter may also be the value returned by
86+
/// `usable_size` for the requested size.
87+
#[inline]
88+
#[allow(unused_variable)] // for the parameter names in the documentation
89+
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
90+
je_dallocx(ptr as *mut c_void, mallocx_align(align))
91+
}
92+
93+
/// Return the usable size of an allocation created with the specified the `size` and `align`.
94+
#[inline]
95+
pub fn usable_size(size: uint, align: uint) -> uint {
96+
unsafe { je_nallocx(size as size_t, mallocx_align(align)) as uint }
97+
}

src/libstd/rt/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ mod macros;
8989
// The global (exchange) heap.
9090
pub mod global_heap;
9191

92-
// Implementations of language-critical runtime features like @.
92+
/// The low-level memory allocation API.
93+
pub mod heap;
94+
95+
/// Implementations of language-critical runtime features like @.
9396
pub mod task;
9497

9598
// The EventLoop and internal synchronous I/O interface.

0 commit comments

Comments
 (0)