@@ -14,7 +14,6 @@
reason = "this library is unlikely to be stabilized in its current \
form or name",
issue = "27783")]
#![feature(alloc_system)]
#![feature(libc)]
#![feature(linkage)]
#![feature(staged_api)]
@@ -23,15 +22,12 @@
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
#![rustc_alloc_kind = "exe"]

extern crate alloc_system;
extern crate libc;

#[cfg(not(dummy_jemalloc))]
pub use contents::*;
#[cfg(not(dummy_jemalloc))]
mod contents {
use core::alloc::{Alloc, AllocErr, Layout};
use alloc_system::System;
use libc::{c_int, c_void, size_t};

// Note that the symbols here are prefixed by default on macOS and Windows (we
@@ -50,18 +46,10 @@ mod contents {
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_rallocx")]
fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_xallocx")]
fn xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_sdallocx")]
fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
#[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_nallocx")]
fn nallocx(size: size_t, flags: c_int) -> size_t;
}

const MALLOCX_ZERO: c_int = 0x40;
@@ -102,20 +90,12 @@ mod contents {

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_alloc(size: usize,
align: usize,
_err: *mut u8) -> *mut u8 {
pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
let flags = align_to_flags(align, size);
let ptr = mallocx(size as size_t, flags) as *mut u8;
ptr
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_oom(err: *const u8) -> ! {
System.oom((*(err as *const AllocErr)).clone())
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
@@ -125,44 +105,20 @@ mod contents {
sdallocx(ptr as *mut c_void, size, flags);
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_usable_size(layout: *const u8,
min: *mut usize,
max: *mut usize) {
let layout = &*(layout as *const Layout);
let flags = align_to_flags(layout.align(), layout.size());
let size = nallocx(layout.size(), flags) as usize;
*min = layout.size();
if size > 0 {
*max = size;
} else {
*max = layout.size();
}
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_realloc(ptr: *mut u8,
_old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize,
_err: *mut u8) -> *mut u8 {
if new_align != old_align {
return 0 as *mut u8
}

let flags = align_to_flags(new_align, new_size);
align: usize,
new_size: usize) -> *mut u8 {
let flags = align_to_flags(align, new_size);
let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
ptr
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_alloc_zeroed(size: usize,
align: usize,
_err: *mut u8) -> *mut u8 {
pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
let ptr = if align <= MIN_ALIGN && align <= size {
calloc(size as size_t, 1) as *mut u8
} else {
@@ -171,60 +127,4 @@ mod contents {
};
ptr
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_alloc_excess(size: usize,
align: usize,
excess: *mut usize,
err: *mut u8) -> *mut u8 {
let p = __rde_alloc(size, align, err);
if !p.is_null() {
let flags = align_to_flags(align, size);
*excess = nallocx(size, flags) as usize;
}
return p
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_realloc_excess(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize,
excess: *mut usize,
err: *mut u8) -> *mut u8 {
let p = __rde_realloc(ptr, old_size, old_align, new_size, new_align, err);
if !p.is_null() {
let flags = align_to_flags(new_align, new_size);
*excess = nallocx(new_size, flags) as usize;
}
p
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_grow_in_place(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize) -> u8 {
__rde_shrink_in_place(ptr, old_size, old_align, new_size, new_align)
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rde_shrink_in_place(ptr: *mut u8,
_old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize) -> u8 {
if old_align == new_align {
let flags = align_to_flags(new_align, new_size);
(xallocx(ptr as *mut c_void, new_size, 0, flags) == new_size) as u8
} else {
0
}
}
}

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -23,51 +23,21 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
inputs: &[AllocatorTy::Layout],
output: AllocatorTy::ResultPtr,
},
AllocatorMethod {
name: "oom",
inputs: &[AllocatorTy::AllocErr],
output: AllocatorTy::Bang,
},
AllocatorMethod {
name: "dealloc",
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
output: AllocatorTy::Unit,
},
AllocatorMethod {
name: "usable_size",
inputs: &[AllocatorTy::LayoutRef],
output: AllocatorTy::UsizePair,
},
AllocatorMethod {
name: "realloc",
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
output: AllocatorTy::ResultPtr,
},
AllocatorMethod {
name: "alloc_zeroed",
inputs: &[AllocatorTy::Layout],
output: AllocatorTy::ResultPtr,
},
AllocatorMethod {
name: "alloc_excess",
inputs: &[AllocatorTy::Layout],
output: AllocatorTy::ResultExcess,
},
AllocatorMethod {
name: "realloc_excess",
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
output: AllocatorTy::ResultExcess,
},
AllocatorMethod {
name: "grow_in_place",
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
output: AllocatorTy::ResultUnit,
},
AllocatorMethod {
name: "shrink_in_place",
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout],
output: AllocatorTy::ResultUnit,
},
];

pub struct AllocatorMethod {
@@ -77,14 +47,9 @@ pub struct AllocatorMethod {
}

pub enum AllocatorTy {
AllocErr,
Bang,
Layout,
LayoutRef,
Ptr,
ResultExcess,
ResultPtr,
ResultUnit,
Unit,
UsizePair,
Usize,
}
@@ -30,7 +30,6 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
};
let i8 = llvm::LLVMInt8TypeInContext(llcx);
let i8p = llvm::LLVMPointerType(i8, 0);
let usizep = llvm::LLVMPointerType(usize, 0);
let void = llvm::LLVMVoidTypeInContext(llcx);

for method in ALLOCATOR_METHODS {
@@ -41,40 +40,19 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
args.push(usize); // size
args.push(usize); // align
}
AllocatorTy::LayoutRef => args.push(i8p),
AllocatorTy::Ptr => args.push(i8p),
AllocatorTy::AllocErr => args.push(i8p),
AllocatorTy::Usize => args.push(usize),

AllocatorTy::Bang |
AllocatorTy::ResultExcess |
AllocatorTy::ResultPtr |
AllocatorTy::ResultUnit |
AllocatorTy::UsizePair |
AllocatorTy::Unit => panic!("invalid allocator arg"),
}
}
let output = match method.output {
AllocatorTy::UsizePair => {
args.push(usizep); // min
args.push(usizep); // max
None
}
AllocatorTy::Bang => None,
AllocatorTy::ResultExcess => {
args.push(i8p); // excess_ptr
args.push(i8p); // err_ptr
Some(i8p)
}
AllocatorTy::ResultPtr => {
args.push(i8p); // err_ptr
Some(i8p)
}
AllocatorTy::ResultUnit => Some(i8),
AllocatorTy::ResultPtr => Some(i8p),
AllocatorTy::Unit => None,

AllocatorTy::AllocErr |
AllocatorTy::Layout |
AllocatorTy::LayoutRef |
AllocatorTy::Usize |
AllocatorTy::Ptr => panic!("invalid allocator output"),
};
let ty = llvm::LLVMFunctionType(output.unwrap_or(void),
@@ -21,7 +21,7 @@
#[doc(hidden)]
#[allow(unused_attributes)]
pub mod __default_lib_allocator {
use super::{System, Layout, Alloc, AllocErr, CannotReallocInPlace};
use super::{System, Layout, GlobalAlloc, Void};
// for symbol names src/librustc/middle/allocator.rs
// for signatures src/librustc_allocator/lib.rs

@@ -30,131 +30,86 @@ pub mod __default_lib_allocator {

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc(size: usize,
align: usize,
_err: *mut u8) -> *mut u8 {
pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
let layout = Layout::from_size_align_unchecked(size, align);
match System.alloc(layout) {
Ok(p) => p,
Err(AllocErr) => 0 as *mut u8,
}
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_oom(err: *const u8) -> ! {
System.oom((*(err as *const AllocErr)).clone())
System.alloc(layout) as *mut u8
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
size: usize,
align: usize) {
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align))
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_usable_size(layout: *const u8,
min: *mut usize,
max: *mut usize) {
let pair = System.usable_size(&*(layout as *const Layout));
*min = pair.0;
*max = pair.1;
System.dealloc(ptr as *mut Void, Layout::from_size_align_unchecked(size, align))
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize,
_err: *mut u8) -> *mut u8 {
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
match System.realloc(ptr, old_layout, new_layout) {
Ok(p) => p,
Err(AllocErr) => 0 as *mut u8,
}
align: usize,
new_size: usize) -> *mut u8 {
let old_layout = Layout::from_size_align_unchecked(old_size, align);
System.realloc(ptr as *mut Void, old_layout, new_size) as *mut u8
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc_zeroed(size: usize,
align: usize,
_err: *mut u8) -> *mut u8 {
pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
let layout = Layout::from_size_align_unchecked(size, align);
match System.alloc_zeroed(layout) {
Ok(p) => p,
Err(AllocErr) => 0 as *mut u8,
}
System.alloc_zeroed(layout) as *mut u8
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc_excess(size: usize,
align: usize,
excess: *mut usize,
_err: *mut u8) -> *mut u8 {
let layout = Layout::from_size_align_unchecked(size, align);
match System.alloc_excess(layout) {
Ok(p) => {
*excess = p.1;
p.0
}
Err(AllocErr) => 0 as *mut u8,
#[cfg(stage0)]
pub mod stage0 {
#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_usable_size(_layout: *const u8,
_min: *mut usize,
_max: *mut usize) {
unimplemented!()
}
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize,
excess: *mut usize,
_err: *mut u8) -> *mut u8 {
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
match System.realloc_excess(ptr, old_layout, new_layout) {
Ok(p) => {
*excess = p.1;
p.0
}
Err(AllocErr) => 0 as *mut u8,
#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc_excess(_size: usize,
_align: usize,
_excess: *mut usize,
_err: *mut u8) -> *mut u8 {
unimplemented!()
}
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize) -> u8 {
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
match System.grow_in_place(ptr, old_layout, new_layout) {
Ok(()) => 1,
Err(CannotReallocInPlace) => 0,
#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_realloc_excess(_ptr: *mut u8,
_old_size: usize,
_old_align: usize,
_new_size: usize,
_new_align: usize,
_excess: *mut usize,
_err: *mut u8) -> *mut u8 {
unimplemented!()
}
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8,
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize) -> u8 {
let old_layout = Layout::from_size_align_unchecked(old_size, old_align);
let new_layout = Layout::from_size_align_unchecked(new_size, new_align);
match System.shrink_in_place(ptr, old_layout, new_layout) {
Ok(()) => 1,
Err(CannotReallocInPlace) => 0,
#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_grow_in_place(_ptr: *mut u8,
_old_size: usize,
_old_align: usize,
_new_size: usize,
_new_align: usize) -> u8 {
unimplemented!()
}

#[no_mangle]
#[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_shrink_in_place(_ptr: *mut u8,
_old_size: usize,
_old_align: usize,
_new_size: usize,
_new_align: usize) -> u8 {
unimplemented!()
}

}
}
@@ -1,4 +1,4 @@
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
2018-03-10
2018-04-05
@@ -12,15 +12,9 @@

#[global_allocator]
static A: usize = 0;
//~^ the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~| the trait bound `&usize:
//~^ the trait bound `usize:
//~| the trait bound `usize:
//~| the trait bound `usize:
//~| the trait bound `usize:

fn main() {}
@@ -11,16 +11,16 @@
#![feature(allocator_api)]
#![crate_type = "rlib"]

use std::heap::*;
use std::alloc::*;

pub struct A;

unsafe impl<'a> Alloc for &'a A {
unsafe fn alloc(&mut self, _: Layout) -> Result<*mut u8, AllocErr> {
unsafe impl GlobalAlloc for A {
unsafe fn alloc(&self, _: Layout) -> *mut Void {
loop {}
}

unsafe fn dealloc(&mut self, _ptr: *mut u8, _: Layout) {
unsafe fn dealloc(&self, _ptr: *mut Void, _: Layout) {
loop {}
}
}
@@ -13,18 +13,18 @@
#![feature(heap_api, allocator_api)]
#![crate_type = "rlib"]

use std::heap::{Alloc, System, AllocErr, Layout};
use std::heap::{GlobalAlloc, System, Layout, Void};
use std::sync::atomic::{AtomicUsize, Ordering};

pub struct A(pub AtomicUsize);

unsafe impl<'a> Alloc for &'a A {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
unsafe impl GlobalAlloc for A {
unsafe fn alloc(&self, layout: Layout) -> *mut Void {
self.0.fetch_add(1, Ordering::SeqCst);
System.alloc(layout)
}

unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
unsafe fn dealloc(&self, ptr: *mut Void, layout: Layout) {
self.0.fetch_add(1, Ordering::SeqCst);
System.dealloc(ptr, layout)
}
@@ -15,20 +15,20 @@

extern crate helper;

use std::heap::{Heap, Alloc, System, Layout, AllocErr};
use std::alloc::{self, Global, Alloc, System, Layout, Void};
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

static HITS: AtomicUsize = ATOMIC_USIZE_INIT;

struct A;

unsafe impl<'a> Alloc for &'a A {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
unsafe impl alloc::GlobalAlloc for A {
unsafe fn alloc(&self, layout: Layout) -> *mut Void {
HITS.fetch_add(1, Ordering::SeqCst);
System.alloc(layout)
}

unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
unsafe fn dealloc(&self, ptr: *mut Void, layout: Layout) {
HITS.fetch_add(1, Ordering::SeqCst);
System.dealloc(ptr, layout)
}
@@ -45,10 +45,10 @@ fn main() {
unsafe {
let layout = Layout::from_size_align(4, 2).unwrap();

let ptr = Heap.alloc(layout.clone()).unwrap();
let ptr = Global.alloc(layout.clone()).unwrap();
helper::work_with(&ptr);
assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
Heap.dealloc(ptr, layout.clone());
Global.dealloc(ptr, layout.clone());
assert_eq!(HITS.load(Ordering::SeqCst), n + 2);

let s = String::with_capacity(10);
@@ -17,7 +17,7 @@
extern crate custom;
extern crate helper;

use std::heap::{Heap, Alloc, System, Layout};
use std::alloc::{Global, Alloc, System, Layout};
use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};

#[global_allocator]
@@ -28,10 +28,10 @@ fn main() {
let n = GLOBAL.0.load(Ordering::SeqCst);
let layout = Layout::from_size_align(4, 2).unwrap();

let ptr = Heap.alloc(layout.clone()).unwrap();
let ptr = Global.alloc(layout.clone()).unwrap();
helper::work_with(&ptr);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
Heap.dealloc(ptr, layout.clone());
Global.dealloc(ptr, layout.clone());
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);

let ptr = System.alloc(layout.clone()).unwrap();
@@ -19,7 +19,7 @@ extern crate custom;
extern crate custom_as_global;
extern crate helper;

use std::heap::{Heap, Alloc, System, Layout};
use std::alloc::{Global, Alloc, GlobalAlloc, System, Layout};
use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};

static GLOBAL: custom::A = custom::A(ATOMIC_USIZE_INIT);
@@ -30,25 +30,25 @@ fn main() {
let layout = Layout::from_size_align(4, 2).unwrap();

// Global allocator routes to the `custom_as_global` global
let ptr = Heap.alloc(layout.clone()).unwrap();
let ptr = Global.alloc(layout.clone()).unwrap();
helper::work_with(&ptr);
assert_eq!(custom_as_global::get(), n + 1);
Heap.dealloc(ptr, layout.clone());
Global.dealloc(ptr, layout.clone());
assert_eq!(custom_as_global::get(), n + 2);

// Usage of the system allocator avoids all globals
let ptr = System.alloc(layout.clone()).unwrap();
let ptr = System.alloc(layout.clone());
helper::work_with(&ptr);
assert_eq!(custom_as_global::get(), n + 2);
System.dealloc(ptr, layout.clone());
assert_eq!(custom_as_global::get(), n + 2);

// Usage of our personal allocator doesn't affect other instances
let ptr = (&GLOBAL).alloc(layout.clone()).unwrap();
let ptr = GLOBAL.alloc(layout.clone());
helper::work_with(&ptr);
assert_eq!(custom_as_global::get(), n + 2);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1);
(&GLOBAL).dealloc(ptr, layout);
GLOBAL.dealloc(ptr, layout);
assert_eq!(custom_as_global::get(), n + 2);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2);
}