Skip to content

add back jemalloc to the tree #13742

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@
[submodule "src/compiler-rt"]
path = src/compiler-rt
url = https://github.com/rust-lang/compiler-rt.git
[submodule "src/jemalloc"]
path = src/jemalloc
url = https://github.com/jemalloc/jemalloc.git
1 change: 1 addition & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,7 @@ do
for s in 0 1 2 3
do
make_dir $t/rt/stage$s
make_dir $t/rt/jemalloc
make_dir $t/rt/libuv
make_dir $t/rt/libuv/src/ares
make_dir $t/rt/libuv/src/eio
Expand Down
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ HOST_CRATES := syntax rustc rustdoc fourcc hexfloat
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc

DEPS_std := libc native:rustrt native:compiler-rt native:backtrace
DEPS_std := libc native:rustrt native:compiler-rt native:backtrace native:jemalloc
DEPS_green := std rand native:context_switch
DEPS_rustuv := std native:uv native:uv_support
DEPS_native := std
Expand Down
48 changes: 44 additions & 4 deletions mk/rt.mk
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,13 @@ $(foreach lib,$(NATIVE_LIBS), \
################################################################################
# Building third-party targets with external build systems
#
# The only current member of this section is libuv, but long ago this used to
# also be occupied by jemalloc. This location is meant for dependencies which
# have external build systems. It is still assumed that the output of each of
# these steps is a static library in the correct location.
# This location is meant for dependencies which have external build systems. It
# is still assumed that the output of each of these steps is a static library
# in the correct location.
################################################################################

################################################################################
# libuv
################################################################################

define DEF_LIBUV_ARCH_VAR
Expand Down Expand Up @@ -160,6 +163,7 @@ else ifeq ($(OSTYPE_$(1)), unknown-freebsd)
else ifeq ($(OSTYPE_$(1)), linux-androideabi)
LIBUV_OSTYPE_$(1) := android
LIBUV_ARGS_$(1) := PLATFORM=android host=android OS=linux
JEMALLOC_ARGS_$(1) := --disable-tls
else
LIBUV_OSTYPE_$(1) := linux
endif
Expand Down Expand Up @@ -219,6 +223,42 @@ $$(LIBUV_DIR_$(1))/Release/libuv.a: $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) \

endif

################################################################################
# jemalloc
################################################################################

ifdef CFG_ENABLE_FAST_MAKE
JEMALLOC_DEPS := $(S)/.gitmodules
else
JEMALLOC_DEPS := $(wildcard \
$(S)src/jemalloc/* \
$(S)src/jemalloc/*/* \
$(S)src/jemalloc/*/*/* \
$(S)src/jemalloc/*/*/*/*)
endif

JEMALLOC_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc)
ifeq ($$(CFG_WINDOWSY_$(1)),1)
JEMALLOC_REAL_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc)
else
JEMALLOC_REAL_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),jemalloc_pic)
endif
JEMALLOC_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(JEMALLOC_NAME_$(1))
JEMALLOC_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/jemalloc

$$(JEMALLOC_LIB_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
@$$(call E, make: jemalloc)
cd "$(S)src/jemalloc"; autoconf
cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je --enable-autogen \
--disable-experimental --build=$(CFG_BUILD_TRIPLE) --host=$(1) \
CC="$$(CC_$(1))" \
AR="$$(AR_$(1))" \
RANLIB="$$(AR_$(1)) s" \
EXTRA_CFLAGS="$$(CFG_GCCISH_CFLAGS)"
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
$$(Q)cp $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1)) $$(JEMALLOC_LIB_$(1))

################################################################################
# compiler-rt
################################################################################
Expand Down
4 changes: 3 additions & 1 deletion mk/tests.mk
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ ALL_HS := $(filter-out $(S)src/rt/vg/valgrind.h \
tidy:
@$(call E, check: formatting)
$(Q)find $(S)src -name '*.r[sc]' \
| grep '^$(S)src/jemalloc' -v \
| grep '^$(S)src/libuv' -v \
| grep '^$(S)src/llvm' -v \
| grep '^$(S)src/gyp' -v \
Expand All @@ -264,8 +265,9 @@ tidy:
$(Q)find $(S)src -type f -perm +111 \
-not -name '*.rs' -and -not -name '*.py' \
-and -not -name '*.sh' \
| grep '^$(S)src/llvm' -v \
| grep '^$(S)src/jemalloc' -v \
| grep '^$(S)src/libuv' -v \
| grep '^$(S)src/llvm' -v \
| grep '^$(S)src/gyp' -v \
| grep '^$(S)src/etc' -v \
| grep '^$(S)src/doc' -v \
Expand Down
1 change: 1 addition & 0 deletions src/jemalloc
Submodule jemalloc added at 46c0af
30 changes: 26 additions & 4 deletions src/libarena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use std::cast::{transmute, transmute_mut, transmute_mut_lifetime};
use std::cast;
use std::cell::{Cell, RefCell};
use std::mem;
use std::mem::min_align_of;
use std::ptr::read;
use std::cmp;
use std::num;
Expand Down Expand Up @@ -204,7 +205,7 @@ impl Arena {
#[inline]
fn alloc_copy<'a, T>(&'a mut self, op: || -> T) -> &'a T {
unsafe {
let ptr = self.alloc_copy_inner(mem::size_of::<T>(), mem::min_align_of::<T>());
let ptr = self.alloc_copy_inner(mem::size_of::<T>(), min_align_of::<T>());
let ptr: *mut T = transmute(ptr);
mem::move_val_init(&mut (*ptr), op());
return transmute(ptr);
Expand Down Expand Up @@ -261,7 +262,7 @@ impl Arena {
unsafe {
let tydesc = get_tydesc::<T>();
let (ty_ptr, ptr) =
self.alloc_noncopy_inner(mem::size_of::<T>(), mem::min_align_of::<T>());
self.alloc_noncopy_inner(mem::size_of::<T>(), min_align_of::<T>());
let ty_ptr: *mut uint = transmute(ty_ptr);
let ptr: *mut T = transmute(ptr);
// Write in our tydesc along with a bit indicating that it
Expand Down Expand Up @@ -354,9 +355,10 @@ struct TypedArenaChunk<T> {

impl<T> TypedArenaChunk<T> {
#[inline]
#[cfg(stage0)]
fn new(next: Option<~TypedArenaChunk<T>>, capacity: uint) -> ~TypedArenaChunk<T> {
let mut size = mem::size_of::<TypedArenaChunk<T>>();
size = round_up(size, mem::min_align_of::<T>());
size = round_up(size, min_align_of::<T>());
let elem_size = mem::size_of::<T>();
let elems_size = elem_size.checked_mul(&capacity).unwrap();
size = size.checked_add(&elems_size).unwrap();
Expand All @@ -372,6 +374,26 @@ impl<T> TypedArenaChunk<T> {
chunk
}

#[inline]
#[cfg(not(stage0))]
fn new(next: Option<~TypedArenaChunk<T>>, capacity: uint) -> ~TypedArenaChunk<T> {
let mut size = mem::size_of::<TypedArenaChunk<T>>();
size = round_up(size, mem::min_align_of::<T>());
let elem_size = mem::size_of::<T>();
let elems_size = elem_size.checked_mul(&capacity).unwrap();
size = size.checked_add(&elems_size).unwrap();

let mut chunk = unsafe {
let chunk = global_heap::exchange_malloc(size, min_align_of::<TypedArenaChunk<T>>());
let mut chunk: ~TypedArenaChunk<T> = cast::transmute(chunk);
mem::move_val_init(&mut chunk.next, next);
chunk
};

chunk.capacity = capacity;
chunk
}

/// Destroys this arena chunk. If the type descriptor is supplied, the
/// drop glue is called; otherwise, drop glue is not called.
#[inline]
Expand Down Expand Up @@ -401,7 +423,7 @@ impl<T> TypedArenaChunk<T> {
fn start(&self) -> *u8 {
let this: *TypedArenaChunk<T> = self;
unsafe {
cast::transmute(round_up(this.offset(1) as uint, mem::min_align_of::<T>()))
cast::transmute(round_up(this.offset(1) as uint, min_align_of::<T>()))
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/trans/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,15 +352,16 @@ fn require_alloc_fn(bcx: &Block, info_ty: ty::t, it: LangItem) -> ast::DefId {

pub fn malloc_raw_dyn<'a>(bcx: &'a Block<'a>,
ptr_ty: ty::t,
size: ValueRef)
size: ValueRef,
align: ValueRef)
-> Result<'a> {
let _icx = push_ctxt("malloc_raw_exchange");
let ccx = bcx.ccx();

// Allocate space:
let r = callee::trans_lang_call(bcx,
require_alloc_fn(bcx, ptr_ty, ExchangeMallocFnLangItem),
[size],
[size, align],
None);

let llty_ptr = type_of::type_of(ccx, ptr_ty);
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use middle::typeck::MethodCall;
use util::common::indenter;
use util::ppaux::Repr;
use util::nodemap::NodeMap;
use middle::trans::machine::{llsize_of, llsize_of_alloc};
use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_alloc};
use middle::trans::type_::Type;

use syntax::ast;
Expand Down Expand Up @@ -1170,10 +1170,11 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>,
let fcx = bcx.fcx;
let llty = type_of::type_of(bcx.ccx(), contents_ty);
let size = llsize_of(bcx.ccx(), llty);
let align = C_uint(bcx.ccx(), llalign_of_min(bcx.ccx(), llty) as uint);
// We need to a make a pointer type because box_ty is ty_bot
// if content_ty is, e.g. ~fail!().
let real_box_ty = ty::mk_uniq(bcx.tcx(), contents_ty);
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size);
let Result { bcx, val } = malloc_raw_dyn(bcx, real_box_ty, size, align);
// Unique boxes do not allocate for zero-size types. The standard library may assume
// that `free` is never called on the pointer returned for `~ZeroSizeType`.
let bcx = if llsize_of_alloc(bcx.ccx(), llty) == 0 {
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/trans/tvec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,9 @@ pub fn trans_uniq_vstore<'a>(bcx: &'a Block<'a>,

let vecsize = Add(bcx, alloc, llsize_of(ccx, ccx.opaque_vec_type));

let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize);
// ~[T] is not going to be changed to support alignment, since it's obsolete.
let align = C_uint(ccx, 8);
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, vec_ty, vecsize, align);
Store(bcx, fill, GEPi(bcx, val, [0u, abi::vec_elt_fill]));
Store(bcx, alloc, GEPi(bcx, val, [0u, abi::vec_elt_alloc]));

Expand Down
19 changes: 18 additions & 1 deletion src/libstd/rt/global_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 {
}

/// The allocator for unique pointers without contained managed pointers.
#[cfg(not(test))]
#[cfg(not(test), stage0)]
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
Expand All @@ -81,6 +81,23 @@ pub unsafe fn exchange_malloc(size: uint) -> *mut u8 {
}
}

/// The allocator for unique pointers without contained managed pointers.
#[cfg(not(test), not(stage0))]
#[lang="exchange_malloc"]
#[inline]
pub unsafe fn exchange_malloc(size: uint, _align: uint) -> *mut u8 {
// The compiler never calls `exchange_free` on ~ZeroSizeType, so zero-size
// allocations can point to this `static`. It would be incorrect to use a null
// pointer, due to enums assuming types like unique pointers are never null.
static EMPTY: () = ();

if size == 0 {
&EMPTY as *() as *mut u8
} else {
malloc_raw(size)
}
}

// FIXME: #7496
#[cfg(not(test))]
#[lang="closure_exchange_malloc"]
Expand Down
93 changes: 93 additions & 0 deletions src/libstd/rt/heap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright 2014 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use intrinsics::{abort, cttz32};
use libc::{c_int, c_void, size_t};
use ptr::RawPtr;

#[link(name = "jemalloc", kind = "static")]
#[link(name = "pthread")]
extern {
fn jemallocx(size: size_t, flags: c_int) -> *mut c_void;
fn jerallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
fn jexallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
fn jedallocx(ptr: *mut c_void, flags: c_int);
fn jenallocx(size: size_t, flags: c_int) -> size_t;
}

// MALLOCX_ALIGN(a) macro
#[inline(always)]
fn mallocx_align(a: uint) -> c_int { unsafe { cttz32(a as u32) as c_int } }

/// Return a pointer to `size` bytes of memory.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
#[inline]
pub unsafe fn allocate(size: uint, align: uint) -> *mut u8 {
let ptr = jemallocx(size as size_t, mallocx_align(align)) as *mut u8;
if ptr.is_null() {
abort()
}
ptr
}

/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to create the
/// allocation referenced by `ptr`. The `old_size` parameter may also be the value returned by
/// `usable_size` for the requested size.
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn reallocate(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> *mut u8 {
let ptr = jerallocx(ptr as *mut c_void, size as size_t, mallocx_align(align)) as *mut u8;
if ptr.is_null() {
abort()
}
ptr
}

/// Extend or shrink the allocation referenced by `ptr` to `size` bytes of memory in-place.
///
/// Return true if successful, otherwise false if the allocation was not altered.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a power of 2. The
/// alignment must be no larger than the largest supported page size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn reallocate_inplace(ptr: *mut u8, size: uint, align: uint, old_size: uint) -> bool {
jexallocx(ptr as *mut c_void, size as size_t, 0, mallocx_align(align)) == size as size_t
}

/// Deallocate the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `size` and `align` parameters are the parameters that were used to create the
/// allocation referenced by `ptr`. The `size` parameter may also be the value returned by
/// `usable_size` for the requested size.
#[inline]
#[allow(unused_variable)] // for the parameter names in the documentation
pub unsafe fn deallocate(ptr: *mut u8, size: uint, align: uint) {
jedallocx(ptr as *mut c_void, mallocx_align(align))
}

/// Return the usable size of an allocation created with the specified the `size` and `align`.
#[inline]
pub fn usable_size(size: uint, align: uint) -> uint {
unsafe { jenallocx(size as size_t, mallocx_align(align)) as uint }
}
3 changes: 3 additions & 0 deletions src/libstd/rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ mod macros;
/// The global (exchange) heap.
pub mod global_heap;

/// The low-level memory allocation API.
pub mod heap;

/// Implementations of language-critical runtime features like @.
pub mod task;

Expand Down