1
Fork 0

Use the GlobalAlloc trait for #[global_allocator]

This commit is contained in:
Simon Sapin 2018-04-03 17:12:57 +02:00
parent eb69593f73
commit 86753ce1cc
17 changed files with 171 additions and 710 deletions

1
src/Cargo.lock generated
View file

@ -19,7 +19,6 @@ dependencies = [
name = "alloc_jemalloc" name = "alloc_jemalloc"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"alloc_system 0.0.0",
"build_helper 0.1.0", "build_helper 0.1.0",
"cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
"compiler_builtins 0.0.0", "compiler_builtins 0.0.0",

View file

@ -29,16 +29,16 @@ looks like:
```rust ```rust
#![feature(global_allocator, allocator_api, heap_api)] #![feature(global_allocator, allocator_api, heap_api)]
use std::heap::{Alloc, System, Layout, AllocErr}; use std::alloc::{GlobalAlloc, System, Layout, Void};
struct MyAllocator; struct MyAllocator;
unsafe impl<'a> Alloc for &'a MyAllocator { unsafe impl GlobalAlloc for MyAllocator {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { unsafe fn alloc(&self, layout: Layout) -> *mut Void {
System.alloc(layout) System.alloc(layout)
} }
unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) { unsafe fn dealloc(&self, ptr: *mut Void, layout: Layout) {
System.dealloc(ptr, layout) System.dealloc(ptr, layout)
} }
} }

View file

@ -16,26 +16,19 @@
issue = "32838")] issue = "32838")]
use core::intrinsics::{min_align_of_val, size_of_val}; use core::intrinsics::{min_align_of_val, size_of_val};
use core::mem;
use core::usize; use core::usize;
#[doc(inline)] #[doc(inline)]
pub use core::alloc::*; pub use core::alloc::*;
#[cfg(stage0)]
extern "Rust" { extern "Rust" {
#[allocator] #[allocator]
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_alloc(size: usize, align: usize, err: *mut u8) -> *mut u8; fn __rust_alloc(size: usize, align: usize, err: *mut u8) -> *mut u8;
#[cold]
#[rustc_allocator_nounwind]
fn __rust_oom(err: *const u8) -> !;
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_usable_size(layout: *const u8,
min: *mut usize,
max: *mut usize);
#[rustc_allocator_nounwind]
fn __rust_realloc(ptr: *mut u8, fn __rust_realloc(ptr: *mut u8,
old_size: usize, old_size: usize,
old_align: usize, old_align: usize,
@ -44,31 +37,22 @@ extern "Rust" {
err: *mut u8) -> *mut u8; err: *mut u8) -> *mut u8;
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8; fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8;
}
#[cfg(not(stage0))]
extern "Rust" {
#[allocator]
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_alloc_excess(size: usize, fn __rust_alloc(size: usize, align: usize) -> *mut u8;
align: usize,
excess: *mut usize,
err: *mut u8) -> *mut u8;
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_realloc_excess(ptr: *mut u8, fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize);
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize,
excess: *mut usize,
err: *mut u8) -> *mut u8;
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_grow_in_place(ptr: *mut u8, fn __rust_realloc(ptr: *mut u8,
old_size: usize, old_size: usize,
old_align: usize, align: usize,
new_size: usize, new_size: usize) -> *mut u8;
new_align: usize) -> u8;
#[rustc_allocator_nounwind] #[rustc_allocator_nounwind]
fn __rust_shrink_in_place(ptr: *mut u8, fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
old_size: usize,
old_align: usize,
new_size: usize,
new_align: usize) -> u8;
} }
#[derive(Copy, Clone, Default, Debug)] #[derive(Copy, Clone, Default, Debug)]
@ -86,22 +70,15 @@ pub const Heap: Global = Global;
unsafe impl Alloc for Global { unsafe impl Alloc for Global {
#[inline] #[inline]
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
let mut err = AllocErr; #[cfg(not(stage0))]
let ptr = __rust_alloc(layout.size(), let ptr = __rust_alloc(layout.size(), layout.align());
layout.align(), #[cfg(stage0)]
&mut err as *mut AllocErr as *mut u8); let ptr = __rust_alloc(layout.size(), layout.align(), &mut 0);
if ptr.is_null() {
Err(AllocErr)
} else {
Ok(ptr)
}
}
#[inline] if !ptr.is_null() {
#[cold] Ok(ptr)
fn oom(&mut self, err: AllocErr) -> ! { } else {
unsafe { Err(AllocErr)
__rust_oom(&err as *const AllocErr as *const u8)
} }
} }
@ -110,18 +87,6 @@ unsafe impl Alloc for Global {
__rust_dealloc(ptr, layout.size(), layout.align()) __rust_dealloc(ptr, layout.size(), layout.align())
} }
#[inline]
fn usable_size(&self, layout: &Layout) -> (usize, usize) {
let mut min = 0;
let mut max = 0;
unsafe {
__rust_usable_size(layout as *const Layout as *const u8,
&mut min,
&mut max);
}
(min, max)
}
#[inline] #[inline]
unsafe fn realloc(&mut self, unsafe fn realloc(&mut self,
ptr: *mut u8, ptr: *mut u8,
@ -129,107 +94,34 @@ unsafe impl Alloc for Global {
new_layout: Layout) new_layout: Layout)
-> Result<*mut u8, AllocErr> -> Result<*mut u8, AllocErr>
{ {
let mut err = AllocErr; if layout.align() == new_layout.align() {
let ptr = __rust_realloc(ptr, #[cfg(not(stage0))]
layout.size(), let ptr = __rust_realloc(ptr, layout.size(), layout.align(), new_layout.size());
layout.align(), #[cfg(stage0)]
new_layout.size(), let ptr = __rust_realloc(ptr, layout.size(), layout.align(),
new_layout.align(), new_layout.size(), new_layout.align(), &mut 0);
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() { if !ptr.is_null() {
Err(AllocErr) Ok(ptr)
} else {
Err(AllocErr)
}
} else { } else {
mem::forget(err); Err(AllocErr)
Ok(ptr)
} }
} }
#[inline] #[inline]
unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
let mut err = AllocErr; #[cfg(not(stage0))]
let ptr = __rust_alloc_zeroed(layout.size(), let ptr = __rust_alloc_zeroed(layout.size(), layout.align());
layout.align(), #[cfg(stage0)]
&mut err as *mut AllocErr as *mut u8); let ptr = __rust_alloc_zeroed(layout.size(), layout.align(), &mut 0);
if ptr.is_null() {
Err(AllocErr) if !ptr.is_null() {
} else {
Ok(ptr) Ok(ptr)
} } else {
}
#[inline]
unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
let mut err = AllocErr;
let mut size = 0;
let ptr = __rust_alloc_excess(layout.size(),
layout.align(),
&mut size,
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() {
Err(AllocErr) Err(AllocErr)
} else {
Ok(Excess(ptr, size))
}
}
#[inline]
unsafe fn realloc_excess(&mut self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout) -> Result<Excess, AllocErr> {
let mut err = AllocErr;
let mut size = 0;
let ptr = __rust_realloc_excess(ptr,
layout.size(),
layout.align(),
new_layout.size(),
new_layout.align(),
&mut size,
&mut err as *mut AllocErr as *mut u8);
if ptr.is_null() {
Err(AllocErr)
} else {
Ok(Excess(ptr, size))
}
}
#[inline]
unsafe fn grow_in_place(&mut self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout)
-> Result<(), CannotReallocInPlace>
{
debug_assert!(new_layout.size() >= layout.size());
debug_assert!(new_layout.align() == layout.align());
let ret = __rust_grow_in_place(ptr,
layout.size(),
layout.align(),
new_layout.size(),
new_layout.align());
if ret != 0 {
Ok(())
} else {
Err(CannotReallocInPlace)
}
}
#[inline]
unsafe fn shrink_in_place(&mut self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout) -> Result<(), CannotReallocInPlace> {
debug_assert!(new_layout.size() <= layout.size());
debug_assert!(new_layout.align() == layout.align());
let ret = __rust_shrink_in_place(ptr,
layout.size(),
layout.align(),
new_layout.size(),
new_layout.align());
if ret != 0 {
Ok(())
} else {
Err(CannotReallocInPlace)
} }
} }
} }

View file

@ -12,7 +12,6 @@ test = false
doc = false doc = false
[dependencies] [dependencies]
alloc_system = { path = "../liballoc_system" }
core = { path = "../libcore" } core = { path = "../libcore" }
libc = { path = "../rustc/libc_shim" } libc = { path = "../rustc/libc_shim" }
compiler_builtins = { path = "../rustc/compiler_builtins_shim" } compiler_builtins = { path = "../rustc/compiler_builtins_shim" }

View file

@ -14,7 +14,6 @@
reason = "this library is unlikely to be stabilized in its current \ reason = "this library is unlikely to be stabilized in its current \
form or name", form or name",
issue = "27783")] issue = "27783")]
#![feature(alloc_system)]
#![feature(libc)] #![feature(libc)]
#![feature(linkage)] #![feature(linkage)]
#![feature(staged_api)] #![feature(staged_api)]
@ -23,15 +22,12 @@
#![cfg_attr(not(dummy_jemalloc), feature(allocator_api))] #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
#![rustc_alloc_kind = "exe"] #![rustc_alloc_kind = "exe"]
extern crate alloc_system;
extern crate libc; extern crate libc;
#[cfg(not(dummy_jemalloc))] #[cfg(not(dummy_jemalloc))]
pub use contents::*; pub use contents::*;
#[cfg(not(dummy_jemalloc))] #[cfg(not(dummy_jemalloc))]
mod contents { mod contents {
use core::alloc::{Alloc, AllocErr, Layout};
use alloc_system::System;
use libc::{c_int, c_void, size_t}; use libc::{c_int, c_void, size_t};
// Note that the symbols here are prefixed by default on macOS and Windows (we // 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"), target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_rallocx")] link_name = "je_rallocx")]
fn rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void; 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", #[cfg_attr(any(target_os = "macos", target_os = "android", target_os = "ios",
target_os = "dragonfly", target_os = "windows", target_env = "musl"), target_os = "dragonfly", target_os = "windows", target_env = "musl"),
link_name = "je_sdallocx")] link_name = "je_sdallocx")]
fn sdallocx(ptr: *mut c_void, size: size_t, flags: c_int); 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; const MALLOCX_ZERO: c_int = 0x40;
@ -102,20 +90,12 @@ mod contents {
#[no_mangle] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rde_alloc(size: usize, pub unsafe extern fn __rde_alloc(size: usize, align: usize) -> *mut u8 {
align: usize,
_err: *mut u8) -> *mut u8 {
let flags = align_to_flags(align, size); let flags = align_to_flags(align, size);
let ptr = mallocx(size as size_t, flags) as *mut u8; let ptr = mallocx(size as size_t, flags) as *mut u8;
ptr 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] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rde_dealloc(ptr: *mut u8, pub unsafe extern fn __rde_dealloc(ptr: *mut u8,
@ -125,44 +105,20 @@ mod contents {
sdallocx(ptr as *mut c_void, size, flags); 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] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rde_realloc(ptr: *mut u8, pub unsafe extern fn __rde_realloc(ptr: *mut u8,
_old_size: usize, _old_size: usize,
old_align: usize, align: usize,
new_size: usize, new_size: usize) -> *mut u8 {
new_align: usize, let flags = align_to_flags(align, new_size);
_err: *mut u8) -> *mut u8 {
if new_align != old_align {
return 0 as *mut u8
}
let flags = align_to_flags(new_align, new_size);
let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8; let ptr = rallocx(ptr as *mut c_void, new_size, flags) as *mut u8;
ptr ptr
} }
#[no_mangle] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rde_alloc_zeroed(size: usize, pub unsafe extern fn __rde_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
align: usize,
_err: *mut u8) -> *mut u8 {
let ptr = if align <= MIN_ALIGN && align <= size { let ptr = if align <= MIN_ALIGN && align <= size {
calloc(size as size_t, 1) as *mut u8 calloc(size as size_t, 1) as *mut u8
} else { } else {
@ -171,60 +127,4 @@ mod contents {
}; };
ptr 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
}
}
} }

View file

@ -11,7 +11,7 @@
use rustc::middle::allocator::AllocatorKind; use rustc::middle::allocator::AllocatorKind;
use rustc_errors; use rustc_errors;
use syntax::abi::Abi; use syntax::abi::Abi;
use syntax::ast::{Crate, Attribute, LitKind, StrStyle, ExprKind}; use syntax::ast::{Crate, Attribute, LitKind, StrStyle};
use syntax::ast::{Unsafety, Constness, Generics, Mutability, Ty, Mac, Arg}; use syntax::ast::{Unsafety, Constness, Generics, Mutability, Ty, Mac, Arg};
use syntax::ast::{self, Ident, Item, ItemKind, TyKind, VisibilityKind, Expr}; use syntax::ast::{self, Ident, Item, ItemKind, TyKind, VisibilityKind, Expr};
use syntax::attr; use syntax::attr;
@ -88,7 +88,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
span, span,
kind: AllocatorKind::Global, kind: AllocatorKind::Global,
global: item.ident, global: item.ident,
alloc: Ident::from_str("alloc"), core: Ident::from_str("core"),
cx: ExtCtxt::new(self.sess, ecfg, self.resolver), cx: ExtCtxt::new(self.sess, ecfg, self.resolver),
}; };
let super_path = f.cx.path(f.span, vec![ let super_path = f.cx.path(f.span, vec![
@ -96,7 +96,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
f.global, f.global,
]); ]);
let mut items = vec![ let mut items = vec![
f.cx.item_extern_crate(f.span, f.alloc), f.cx.item_extern_crate(f.span, f.core),
f.cx.item_use_simple( f.cx.item_use_simple(
f.span, f.span,
respan(f.span.shrink_to_lo(), VisibilityKind::Inherited), respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
@ -126,7 +126,7 @@ struct AllocFnFactory<'a> {
span: Span, span: Span,
kind: AllocatorKind, kind: AllocatorKind,
global: Ident, global: Ident,
alloc: Ident, core: Ident,
cx: ExtCtxt<'a>, cx: ExtCtxt<'a>,
} }
@ -143,8 +143,7 @@ impl<'a> AllocFnFactory<'a> {
self.arg_ty(ty, &mut abi_args, mk) self.arg_ty(ty, &mut abi_args, mk)
}).collect(); }).collect();
let result = self.call_allocator(method.name, args); let result = self.call_allocator(method.name, args);
let (output_ty, output_expr) = let (output_ty, output_expr) = self.ret_ty(&method.output, result);
self.ret_ty(&method.output, &mut abi_args, mk, result);
let kind = ItemKind::Fn(self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)), let kind = ItemKind::Fn(self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)),
Unsafety::Unsafe, Unsafety::Unsafe,
dummy_spanned(Constness::NotConst), dummy_spanned(Constness::NotConst),
@ -159,16 +158,15 @@ impl<'a> AllocFnFactory<'a> {
fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> { fn call_allocator(&self, method: &str, mut args: Vec<P<Expr>>) -> P<Expr> {
let method = self.cx.path(self.span, vec![ let method = self.cx.path(self.span, vec![
self.alloc, self.core,
Ident::from_str("heap"), Ident::from_str("alloc"),
Ident::from_str("Alloc"), Ident::from_str("GlobalAlloc"),
Ident::from_str(method), Ident::from_str(method),
]); ]);
let method = self.cx.expr_path(method); let method = self.cx.expr_path(method);
let allocator = self.cx.path_ident(self.span, self.global); let allocator = self.cx.path_ident(self.span, self.global);
let allocator = self.cx.expr_path(allocator); let allocator = self.cx.expr_path(allocator);
let allocator = self.cx.expr_addr_of(self.span, allocator); let allocator = self.cx.expr_addr_of(self.span, allocator);
let allocator = self.cx.expr_mut_addr_of(self.span, allocator);
args.insert(0, allocator); args.insert(0, allocator);
self.cx.expr_call(self.span, method, args) self.cx.expr_call(self.span, method, args)
@ -205,8 +203,8 @@ impl<'a> AllocFnFactory<'a> {
args.push(self.cx.arg(self.span, align, ty_usize)); args.push(self.cx.arg(self.span, align, ty_usize));
let layout_new = self.cx.path(self.span, vec![ let layout_new = self.cx.path(self.span, vec![
self.alloc, self.core,
Ident::from_str("heap"), Ident::from_str("alloc"),
Ident::from_str("Layout"), Ident::from_str("Layout"),
Ident::from_str("from_size_align_unchecked"), Ident::from_str("from_size_align_unchecked"),
]); ]);
@ -219,286 +217,67 @@ impl<'a> AllocFnFactory<'a> {
layout layout
} }
AllocatorTy::LayoutRef => {
let ident = ident();
args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
// Convert our `arg: *const u8` via:
//
// &*(arg as *const Layout)
let expr = self.cx.expr_ident(self.span, ident);
let expr = self.cx.expr_cast(self.span, expr, self.layout_ptr());
let expr = self.cx.expr_deref(self.span, expr);
self.cx.expr_addr_of(self.span, expr)
}
AllocatorTy::AllocErr => {
// We're creating:
//
// (*(arg as *const AllocErr)).clone()
let ident = ident();
args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
let expr = self.cx.expr_ident(self.span, ident);
let expr = self.cx.expr_cast(self.span, expr, self.alloc_err_ptr());
let expr = self.cx.expr_deref(self.span, expr);
self.cx.expr_method_call(
self.span,
expr,
Ident::from_str("clone"),
Vec::new()
)
}
AllocatorTy::Ptr => { AllocatorTy::Ptr => {
let ident = ident(); let ident = ident();
args.push(self.cx.arg(self.span, ident, self.ptr_u8())); args.push(self.cx.arg(self.span, ident, self.ptr_u8()));
let arg = self.cx.expr_ident(self.span, ident);
self.cx.expr_cast(self.span, arg, self.ptr_void())
}
AllocatorTy::Usize => {
let ident = ident();
args.push(self.cx.arg(self.span, ident, self.usize()));
self.cx.expr_ident(self.span, ident) self.cx.expr_ident(self.span, ident)
} }
AllocatorTy::ResultPtr | AllocatorTy::ResultPtr |
AllocatorTy::ResultExcess |
AllocatorTy::ResultUnit |
AllocatorTy::Bang |
AllocatorTy::UsizePair |
AllocatorTy::Unit => { AllocatorTy::Unit => {
panic!("can't convert AllocatorTy to an argument") panic!("can't convert AllocatorTy to an argument")
} }
} }
} }
fn ret_ty(&self, fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
ty: &AllocatorTy,
args: &mut Vec<Arg>,
ident: &mut FnMut() -> Ident,
expr: P<Expr>) -> (P<Ty>, P<Expr>)
{
match *ty { match *ty {
AllocatorTy::UsizePair => {
// We're creating:
//
// let arg = #expr;
// *min = arg.0;
// *max = arg.1;
let min = ident();
let max = ident();
args.push(self.cx.arg(self.span, min, self.ptr_usize()));
args.push(self.cx.arg(self.span, max, self.ptr_usize()));
let ident = ident();
let stmt = self.cx.stmt_let(self.span, false, ident, expr);
let min = self.cx.expr_ident(self.span, min);
let max = self.cx.expr_ident(self.span, max);
let layout = self.cx.expr_ident(self.span, ident);
let assign_min = self.cx.expr(self.span, ExprKind::Assign(
self.cx.expr_deref(self.span, min),
self.cx.expr_tup_field_access(self.span, layout.clone(), 0),
));
let assign_min = self.cx.stmt_semi(assign_min);
let assign_max = self.cx.expr(self.span, ExprKind::Assign(
self.cx.expr_deref(self.span, max),
self.cx.expr_tup_field_access(self.span, layout.clone(), 1),
));
let assign_max = self.cx.stmt_semi(assign_max);
let stmts = vec![stmt, assign_min, assign_max];
let block = self.cx.block(self.span, stmts);
let ty_unit = self.cx.ty(self.span, TyKind::Tup(Vec::new()));
(ty_unit, self.cx.expr_block(block))
}
AllocatorTy::ResultExcess => {
// We're creating:
//
// match #expr {
// Ok(ptr) => {
// *excess = ptr.1;
// ptr.0
// }
// Err(e) => {
// ptr::write(err_ptr, e);
// 0 as *mut u8
// }
// }
let excess_ptr = ident();
args.push(self.cx.arg(self.span, excess_ptr, self.ptr_usize()));
let excess_ptr = self.cx.expr_ident(self.span, excess_ptr);
let err_ptr = ident();
args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8()));
let err_ptr = self.cx.expr_ident(self.span, err_ptr);
let err_ptr = self.cx.expr_cast(self.span,
err_ptr,
self.alloc_err_ptr());
let name = ident();
let ok_expr = {
let ptr = self.cx.expr_ident(self.span, name);
let write = self.cx.expr(self.span, ExprKind::Assign(
self.cx.expr_deref(self.span, excess_ptr),
self.cx.expr_tup_field_access(self.span, ptr.clone(), 1),
));
let write = self.cx.stmt_semi(write);
let ret = self.cx.expr_tup_field_access(self.span,
ptr.clone(),
0);
let ret = self.cx.stmt_expr(ret);
let block = self.cx.block(self.span, vec![write, ret]);
self.cx.expr_block(block)
};
let pat = self.cx.pat_ident(self.span, name);
let ok = self.cx.path_ident(self.span, Ident::from_str("Ok"));
let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]);
let ok = self.cx.arm(self.span, vec![ok], ok_expr);
let name = ident();
let err_expr = {
let err = self.cx.expr_ident(self.span, name);
let write = self.cx.path(self.span, vec![
self.alloc,
Ident::from_str("heap"),
Ident::from_str("__core"),
Ident::from_str("ptr"),
Ident::from_str("write"),
]);
let write = self.cx.expr_path(write);
let write = self.cx.expr_call(self.span, write,
vec![err_ptr, err]);
let write = self.cx.stmt_semi(write);
let null = self.cx.expr_usize(self.span, 0);
let null = self.cx.expr_cast(self.span, null, self.ptr_u8());
let null = self.cx.stmt_expr(null);
let block = self.cx.block(self.span, vec![write, null]);
self.cx.expr_block(block)
};
let pat = self.cx.pat_ident(self.span, name);
let err = self.cx.path_ident(self.span, Ident::from_str("Err"));
let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]);
let err = self.cx.arm(self.span, vec![err], err_expr);
let expr = self.cx.expr_match(self.span, expr, vec![ok, err]);
(self.ptr_u8(), expr)
}
AllocatorTy::ResultPtr => { AllocatorTy::ResultPtr => {
// We're creating: // We're creating:
// //
// match #expr { // #expr as *mut u8
// Ok(ptr) => ptr,
// Err(e) => {
// ptr::write(err_ptr, e);
// 0 as *mut u8
// }
// }
let err_ptr = ident(); let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
args.push(self.cx.arg(self.span, err_ptr, self.ptr_u8()));
let err_ptr = self.cx.expr_ident(self.span, err_ptr);
let err_ptr = self.cx.expr_cast(self.span,
err_ptr,
self.alloc_err_ptr());
let name = ident();
let ok_expr = self.cx.expr_ident(self.span, name);
let pat = self.cx.pat_ident(self.span, name);
let ok = self.cx.path_ident(self.span, Ident::from_str("Ok"));
let ok = self.cx.pat_tuple_struct(self.span, ok, vec![pat]);
let ok = self.cx.arm(self.span, vec![ok], ok_expr);
let name = ident();
let err_expr = {
let err = self.cx.expr_ident(self.span, name);
let write = self.cx.path(self.span, vec![
self.alloc,
Ident::from_str("heap"),
Ident::from_str("__core"),
Ident::from_str("ptr"),
Ident::from_str("write"),
]);
let write = self.cx.expr_path(write);
let write = self.cx.expr_call(self.span, write,
vec![err_ptr, err]);
let write = self.cx.stmt_semi(write);
let null = self.cx.expr_usize(self.span, 0);
let null = self.cx.expr_cast(self.span, null, self.ptr_u8());
let null = self.cx.stmt_expr(null);
let block = self.cx.block(self.span, vec![write, null]);
self.cx.expr_block(block)
};
let pat = self.cx.pat_ident(self.span, name);
let err = self.cx.path_ident(self.span, Ident::from_str("Err"));
let err = self.cx.pat_tuple_struct(self.span, err, vec![pat]);
let err = self.cx.arm(self.span, vec![err], err_expr);
let expr = self.cx.expr_match(self.span, expr, vec![ok, err]);
(self.ptr_u8(), expr) (self.ptr_u8(), expr)
} }
AllocatorTy::ResultUnit => {
// We're creating:
//
// #expr.is_ok() as u8
let cast = self.cx.expr_method_call(
self.span,
expr,
Ident::from_str("is_ok"),
Vec::new()
);
let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
let u8 = self.cx.ty_path(u8);
let cast = self.cx.expr_cast(self.span, cast, u8.clone());
(u8, cast)
}
AllocatorTy::Bang => {
(self.cx.ty(self.span, TyKind::Never), expr)
}
AllocatorTy::Unit => { AllocatorTy::Unit => {
(self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr) (self.cx.ty(self.span, TyKind::Tup(Vec::new())), expr)
} }
AllocatorTy::AllocErr |
AllocatorTy::Layout | AllocatorTy::Layout |
AllocatorTy::LayoutRef | AllocatorTy::Usize |
AllocatorTy::Ptr => { AllocatorTy::Ptr => {
panic!("can't convert AllocatorTy to an output") panic!("can't convert AllocatorTy to an output")
} }
} }
} }
fn usize(&self) -> P<Ty> {
let usize = self.cx.path_ident(self.span, Ident::from_str("usize"));
self.cx.ty_path(usize)
}
fn ptr_u8(&self) -> P<Ty> { fn ptr_u8(&self) -> P<Ty> {
let u8 = self.cx.path_ident(self.span, Ident::from_str("u8")); let u8 = self.cx.path_ident(self.span, Ident::from_str("u8"));
let ty_u8 = self.cx.ty_path(u8); let ty_u8 = self.cx.ty_path(u8);
self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable) self.cx.ty_ptr(self.span, ty_u8, Mutability::Mutable)
} }
fn ptr_usize(&self) -> P<Ty> { fn ptr_void(&self) -> P<Ty> {
let usize = self.cx.path_ident(self.span, Ident::from_str("usize")); let void = self.cx.path(self.span, vec![
let ty_usize = self.cx.ty_path(usize); self.core,
self.cx.ty_ptr(self.span, ty_usize, Mutability::Mutable) Ident::from_str("alloc"),
} Ident::from_str("Void"),
fn layout_ptr(&self) -> P<Ty> {
let layout = self.cx.path(self.span, vec![
self.alloc,
Ident::from_str("heap"),
Ident::from_str("Layout"),
]); ]);
let layout = self.cx.ty_path(layout); let ty_void = self.cx.ty_path(void);
self.cx.ty_ptr(self.span, layout, Mutability::Mutable) self.cx.ty_ptr(self.span, ty_void, Mutability::Mutable)
}
fn alloc_err_ptr(&self) -> P<Ty> {
let err = self.cx.path(self.span, vec![
self.alloc,
Ident::from_str("heap"),
Ident::from_str("AllocErr"),
]);
let err = self.cx.ty_path(err);
self.cx.ty_ptr(self.span, err, Mutability::Mutable)
} }
} }

View file

@ -23,24 +23,14 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
inputs: &[AllocatorTy::Layout], inputs: &[AllocatorTy::Layout],
output: AllocatorTy::ResultPtr, output: AllocatorTy::ResultPtr,
}, },
AllocatorMethod {
name: "oom",
inputs: &[AllocatorTy::AllocErr],
output: AllocatorTy::Bang,
},
AllocatorMethod { AllocatorMethod {
name: "dealloc", name: "dealloc",
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout], inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout],
output: AllocatorTy::Unit, output: AllocatorTy::Unit,
}, },
AllocatorMethod {
name: "usable_size",
inputs: &[AllocatorTy::LayoutRef],
output: AllocatorTy::UsizePair,
},
AllocatorMethod { AllocatorMethod {
name: "realloc", name: "realloc",
inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Usize],
output: AllocatorTy::ResultPtr, output: AllocatorTy::ResultPtr,
}, },
AllocatorMethod { AllocatorMethod {
@ -48,26 +38,6 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[
inputs: &[AllocatorTy::Layout], inputs: &[AllocatorTy::Layout],
output: AllocatorTy::ResultPtr, 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 { pub struct AllocatorMethod {
@ -77,14 +47,9 @@ pub struct AllocatorMethod {
} }
pub enum AllocatorTy { pub enum AllocatorTy {
AllocErr,
Bang,
Layout, Layout,
LayoutRef,
Ptr, Ptr,
ResultExcess,
ResultPtr, ResultPtr,
ResultUnit,
Unit, Unit,
UsizePair, Usize,
} }

View file

@ -30,7 +30,6 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
}; };
let i8 = llvm::LLVMInt8TypeInContext(llcx); let i8 = llvm::LLVMInt8TypeInContext(llcx);
let i8p = llvm::LLVMPointerType(i8, 0); let i8p = llvm::LLVMPointerType(i8, 0);
let usizep = llvm::LLVMPointerType(usize, 0);
let void = llvm::LLVMVoidTypeInContext(llcx); let void = llvm::LLVMVoidTypeInContext(llcx);
for method in ALLOCATOR_METHODS { 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); // size
args.push(usize); // align args.push(usize); // align
} }
AllocatorTy::LayoutRef => args.push(i8p),
AllocatorTy::Ptr => 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::ResultPtr |
AllocatorTy::ResultUnit |
AllocatorTy::UsizePair |
AllocatorTy::Unit => panic!("invalid allocator arg"), AllocatorTy::Unit => panic!("invalid allocator arg"),
} }
} }
let output = match method.output { let output = match method.output {
AllocatorTy::UsizePair => { AllocatorTy::ResultPtr => Some(i8p),
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::Unit => None, AllocatorTy::Unit => None,
AllocatorTy::AllocErr |
AllocatorTy::Layout | AllocatorTy::Layout |
AllocatorTy::LayoutRef | AllocatorTy::Usize |
AllocatorTy::Ptr => panic!("invalid allocator output"), AllocatorTy::Ptr => panic!("invalid allocator output"),
}; };
let ty = llvm::LLVMFunctionType(output.unwrap_or(void), let ty = llvm::LLVMFunctionType(output.unwrap_or(void),

View file

@ -21,7 +21,7 @@
#[doc(hidden)] #[doc(hidden)]
#[allow(unused_attributes)] #[allow(unused_attributes)]
pub mod __default_lib_allocator { 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 symbol names src/librustc/middle/allocator.rs
// for signatures src/librustc_allocator/lib.rs // for signatures src/librustc_allocator/lib.rs
@ -30,20 +30,9 @@ pub mod __default_lib_allocator {
#[no_mangle] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc(size: usize, pub unsafe extern fn __rdl_alloc(size: usize, align: usize) -> *mut u8 {
align: usize,
_err: *mut u8) -> *mut u8 {
let layout = Layout::from_size_align_unchecked(size, align); let layout = Layout::from_size_align_unchecked(size, align);
match System.alloc(layout) { System.alloc(layout) as *mut u8
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())
} }
#[no_mangle] #[no_mangle]
@ -51,110 +40,76 @@ pub mod __default_lib_allocator {
pub unsafe extern fn __rdl_dealloc(ptr: *mut u8, pub unsafe extern fn __rdl_dealloc(ptr: *mut u8,
size: usize, size: usize,
align: usize) { align: usize) {
System.dealloc(ptr, Layout::from_size_align_unchecked(size, align)) System.dealloc(ptr as *mut Void, 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;
} }
#[no_mangle] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_realloc(ptr: *mut u8, pub unsafe extern fn __rdl_realloc(ptr: *mut u8,
old_size: usize, old_size: usize,
old_align: usize, align: usize,
new_size: usize, new_size: usize) -> *mut u8 {
new_align: usize, let old_layout = Layout::from_size_align_unchecked(old_size, align);
_err: *mut u8) -> *mut u8 { System.realloc(ptr as *mut Void, old_layout, new_size) as *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,
}
} }
#[no_mangle] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_alloc_zeroed(size: usize, pub unsafe extern fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
align: usize,
_err: *mut u8) -> *mut u8 {
let layout = Layout::from_size_align_unchecked(size, align); let layout = Layout::from_size_align_unchecked(size, align);
match System.alloc_zeroed(layout) { System.alloc_zeroed(layout) as *mut u8
Ok(p) => p,
Err(AllocErr) => 0 as *mut u8,
}
} }
#[no_mangle] #[cfg(stage0)]
#[rustc_std_internal_symbol] pub mod stage0 {
pub unsafe extern fn __rdl_alloc_excess(size: usize, #[no_mangle]
align: usize, #[rustc_std_internal_symbol]
excess: *mut usize, pub unsafe extern fn __rdl_usable_size(_layout: *const u8,
_err: *mut u8) -> *mut u8 { _min: *mut usize,
let layout = Layout::from_size_align_unchecked(size, align); _max: *mut usize) {
match System.alloc_excess(layout) { unimplemented!()
Ok(p) => {
*excess = p.1;
p.0
}
Err(AllocErr) => 0 as *mut u8,
} }
}
#[no_mangle] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_realloc_excess(ptr: *mut u8, pub unsafe extern fn __rdl_alloc_excess(_size: usize,
old_size: usize, _align: usize,
old_align: usize, _excess: *mut usize,
new_size: usize, _err: *mut u8) -> *mut u8 {
new_align: usize, unimplemented!()
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] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_grow_in_place(ptr: *mut u8, pub unsafe extern fn __rdl_realloc_excess(_ptr: *mut u8,
old_size: usize, _old_size: usize,
old_align: usize, _old_align: usize,
new_size: usize, _new_size: usize,
new_align: usize) -> u8 { _new_align: usize,
let old_layout = Layout::from_size_align_unchecked(old_size, old_align); _excess: *mut usize,
let new_layout = Layout::from_size_align_unchecked(new_size, new_align); _err: *mut u8) -> *mut u8 {
match System.grow_in_place(ptr, old_layout, new_layout) { unimplemented!()
Ok(()) => 1,
Err(CannotReallocInPlace) => 0,
} }
}
#[no_mangle] #[no_mangle]
#[rustc_std_internal_symbol] #[rustc_std_internal_symbol]
pub unsafe extern fn __rdl_shrink_in_place(ptr: *mut u8, pub unsafe extern fn __rdl_grow_in_place(_ptr: *mut u8,
old_size: usize, _old_size: usize,
old_align: usize, _old_align: usize,
new_size: usize, _new_size: usize,
new_align: usize) -> u8 { _new_align: usize) -> u8 {
let old_layout = Layout::from_size_align_unchecked(old_size, old_align); unimplemented!()
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_shrink_in_place(_ptr: *mut u8,
_old_size: usize,
_old_align: usize,
_new_size: usize,
_new_align: usize) -> u8 {
unimplemented!()
}
} }
} }

@ -1 +1 @@
Subproject commit 6ceaaa4b0176a200e4bbd347d6a991ab6c776ede Subproject commit 7243155b1c3da0a980c868a87adebf00e0b33989

View file

@ -1,4 +1,4 @@
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt. # 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 # 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. # build bots then the contents should be changed so git updates the mtime.
2018-03-10 2018-04-05

View file

@ -12,15 +12,9 @@
#[global_allocator] #[global_allocator]
static A: usize = 0; 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() {} fn main() {}

View file

@ -11,16 +11,16 @@
#![feature(allocator_api)] #![feature(allocator_api)]
#![crate_type = "rlib"] #![crate_type = "rlib"]
use std::heap::*; use std::alloc::*;
pub struct A; pub struct A;
unsafe impl<'a> Alloc for &'a A { unsafe impl GlobalAlloc for A {
unsafe fn alloc(&mut self, _: Layout) -> Result<*mut u8, AllocErr> { unsafe fn alloc(&self, _: Layout) -> *mut Void {
loop {} loop {}
} }
unsafe fn dealloc(&mut self, _ptr: *mut u8, _: Layout) { unsafe fn dealloc(&self, _ptr: *mut Void, _: Layout) {
loop {} loop {}
} }
} }

View file

@ -13,18 +13,18 @@
#![feature(heap_api, allocator_api)] #![feature(heap_api, allocator_api)]
#![crate_type = "rlib"] #![crate_type = "rlib"]
use std::heap::{Alloc, System, AllocErr, Layout}; use std::heap::{GlobalAlloc, System, Layout, Void};
use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::atomic::{AtomicUsize, Ordering};
pub struct A(pub AtomicUsize); pub struct A(pub AtomicUsize);
unsafe impl<'a> Alloc for &'a A { unsafe impl GlobalAlloc for A {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { unsafe fn alloc(&self, layout: Layout) -> *mut Void {
self.0.fetch_add(1, Ordering::SeqCst); self.0.fetch_add(1, Ordering::SeqCst);
System.alloc(layout) 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); self.0.fetch_add(1, Ordering::SeqCst);
System.dealloc(ptr, layout) System.dealloc(ptr, layout)
} }

View file

@ -15,20 +15,20 @@
extern crate helper; 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}; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
static HITS: AtomicUsize = ATOMIC_USIZE_INIT; static HITS: AtomicUsize = ATOMIC_USIZE_INIT;
struct A; struct A;
unsafe impl<'a> Alloc for &'a A { unsafe impl alloc::GlobalAlloc for A {
unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> { unsafe fn alloc(&self, layout: Layout) -> *mut Void {
HITS.fetch_add(1, Ordering::SeqCst); HITS.fetch_add(1, Ordering::SeqCst);
System.alloc(layout) 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); HITS.fetch_add(1, Ordering::SeqCst);
System.dealloc(ptr, layout) System.dealloc(ptr, layout)
} }
@ -45,10 +45,10 @@ fn main() {
unsafe { unsafe {
let layout = Layout::from_size_align(4, 2).unwrap(); 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); helper::work_with(&ptr);
assert_eq!(HITS.load(Ordering::SeqCst), n + 1); 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); assert_eq!(HITS.load(Ordering::SeqCst), n + 2);
let s = String::with_capacity(10); let s = String::with_capacity(10);

View file

@ -17,7 +17,7 @@
extern crate custom; extern crate custom;
extern crate helper; 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}; use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};
#[global_allocator] #[global_allocator]
@ -28,10 +28,10 @@ fn main() {
let n = GLOBAL.0.load(Ordering::SeqCst); let n = GLOBAL.0.load(Ordering::SeqCst);
let layout = Layout::from_size_align(4, 2).unwrap(); 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); helper::work_with(&ptr);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); 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); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
let ptr = System.alloc(layout.clone()).unwrap(); let ptr = System.alloc(layout.clone()).unwrap();

View file

@ -19,7 +19,7 @@ extern crate custom;
extern crate custom_as_global; extern crate custom_as_global;
extern crate helper; 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}; use std::sync::atomic::{Ordering, ATOMIC_USIZE_INIT};
static GLOBAL: custom::A = custom::A(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(); let layout = Layout::from_size_align(4, 2).unwrap();
// Global allocator routes to the `custom_as_global` global // 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); helper::work_with(&ptr);
assert_eq!(custom_as_global::get(), n + 1); 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); assert_eq!(custom_as_global::get(), n + 2);
// Usage of the system allocator avoids all globals // 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); helper::work_with(&ptr);
assert_eq!(custom_as_global::get(), n + 2); assert_eq!(custom_as_global::get(), n + 2);
System.dealloc(ptr, layout.clone()); System.dealloc(ptr, layout.clone());
assert_eq!(custom_as_global::get(), n + 2); assert_eq!(custom_as_global::get(), n + 2);
// Usage of our personal allocator doesn't affect other instances // 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); helper::work_with(&ptr);
assert_eq!(custom_as_global::get(), n + 2); assert_eq!(custom_as_global::get(), n + 2);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1); 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!(custom_as_global::get(), n + 2);
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2);
} }