Use the GlobalAlloc trait for #[global_allocator]
This commit is contained in:
parent
eb69593f73
commit
86753ce1cc
17 changed files with 171 additions and 710 deletions
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" }
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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!()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
src/llvm
2
src/llvm
|
@ -1 +1 @@
|
||||||
Subproject commit 6ceaaa4b0176a200e4bbd347d6a991ab6c776ede
|
Subproject commit 7243155b1c3da0a980c868a87adebf00e0b33989
|
|
@ -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
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
|
@ -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 {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue