Auto merge of #70362 - TimDiekmann:alloc-overhaul, r=Amanieu
Overhaul of the `AllocRef` trait to match allocator-wg's latest consens; Take 2 GitHub won't let me reopen #69889 so I make a new PR. In addition to #69889 this fixes the unsoundness of `RawVec::into_box` when using allocators supporting overallocating. Also it uses `MemoryBlock` in `AllocRef` to unify `_in_place` methods by passing `&mut MemoryBlock`. Additionally, `RawVec` now checks for `size_of::<T>()` again and ignore every ZST. The internal capacity of `RawVec` isn't used by ZSTs anymore, as `into_box` now requires a length to be specified. r? @Amanieu fixes rust-lang/wg-allocators#38 fixes rust-lang/wg-allocators#41 fixes rust-lang/wg-allocators#44 fixes rust-lang/wg-allocators#51
This commit is contained in:
commit
127a11a344
21 changed files with 1453 additions and 1627 deletions
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
extern crate helper;
|
||||
|
||||
use std::alloc::{self, Global, AllocRef, System, Layout};
|
||||
use std::alloc::{self, AllocInit, AllocRef, Global, Layout, System};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
static HITS: AtomicUsize = AtomicUsize::new(0);
|
||||
|
|
@ -37,10 +37,10 @@ fn main() {
|
|||
unsafe {
|
||||
let layout = Layout::from_size_align(4, 2).unwrap();
|
||||
|
||||
let (ptr, _) = Global.alloc(layout.clone()).unwrap();
|
||||
helper::work_with(&ptr);
|
||||
let memory = Global.alloc(layout.clone(), AllocInit::Uninitialized).unwrap();
|
||||
helper::work_with(&memory.ptr);
|
||||
assert_eq!(HITS.load(Ordering::SeqCst), n + 1);
|
||||
Global.dealloc(ptr, layout.clone());
|
||||
Global.dealloc(memory.ptr, layout);
|
||||
assert_eq!(HITS.load(Ordering::SeqCst), n + 2);
|
||||
|
||||
let s = String::with_capacity(10);
|
||||
|
|
@ -49,10 +49,10 @@ fn main() {
|
|||
drop(s);
|
||||
assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
|
||||
|
||||
let (ptr, _) = System.alloc(layout.clone()).unwrap();
|
||||
let memory = System.alloc(layout.clone(), AllocInit::Uninitialized).unwrap();
|
||||
assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
|
||||
helper::work_with(&ptr);
|
||||
System.dealloc(ptr, layout);
|
||||
helper::work_with(&memory.ptr);
|
||||
System.dealloc(memory.ptr, layout);
|
||||
assert_eq!(HITS.load(Ordering::SeqCst), n + 4);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@
|
|||
extern crate custom;
|
||||
extern crate helper;
|
||||
|
||||
use std::alloc::{Global, AllocRef, System, Layout};
|
||||
use std::sync::atomic::{Ordering, AtomicUsize};
|
||||
use std::alloc::{AllocInit, AllocRef, Global, Layout, System};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
#[global_allocator]
|
||||
static GLOBAL: custom::A = custom::A(AtomicUsize::new(0));
|
||||
|
|
@ -20,16 +20,16 @@ fn main() {
|
|||
let n = GLOBAL.0.load(Ordering::SeqCst);
|
||||
let layout = Layout::from_size_align(4, 2).unwrap();
|
||||
|
||||
let (ptr, _) = Global.alloc(layout.clone()).unwrap();
|
||||
helper::work_with(&ptr);
|
||||
let memory = Global.alloc(layout.clone(), AllocInit::Uninitialized).unwrap();
|
||||
helper::work_with(&memory.ptr);
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1);
|
||||
Global.dealloc(ptr, layout.clone());
|
||||
Global.dealloc(memory.ptr, layout);
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
|
||||
|
||||
let (ptr, _) = System.alloc(layout.clone()).unwrap();
|
||||
let memory = System.alloc(layout.clone(), AllocInit::Uninitialized).unwrap();
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
|
||||
helper::work_with(&ptr);
|
||||
System.dealloc(ptr, layout);
|
||||
helper::work_with(&memory.ptr);
|
||||
System.dealloc(memory.ptr, layout);
|
||||
assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#![feature(allocator_api)]
|
||||
|
||||
use std::alloc::{Global, AllocRef, Layout, handle_alloc_error};
|
||||
use std::alloc::{handle_alloc_error, AllocInit, AllocRef, Global, Layout, ReallocPlacement};
|
||||
use std::ptr::{self, NonNull};
|
||||
|
||||
fn main() {
|
||||
|
|
@ -16,17 +16,17 @@ fn main() {
|
|||
}
|
||||
|
||||
unsafe fn test_triangle() -> bool {
|
||||
static COUNT : usize = 16;
|
||||
static COUNT: usize = 16;
|
||||
let mut ascend = vec![ptr::null_mut(); COUNT];
|
||||
let ascend = &mut *ascend;
|
||||
static ALIGN : usize = 1;
|
||||
static ALIGN: usize = 1;
|
||||
|
||||
// Checks that `ascend` forms triangle of ascending size formed
|
||||
// from pairs of rows (where each pair of rows is equally sized),
|
||||
// and the elements of the triangle match their row-pair index.
|
||||
unsafe fn sanity_check(ascend: &[*mut u8]) {
|
||||
for i in 0..COUNT / 2 {
|
||||
let (p0, p1, size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
|
||||
let (p0, p1, size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i));
|
||||
for j in 0..size {
|
||||
assert_eq!(*p0.add(j), i as u8);
|
||||
assert_eq!(*p1.add(j), i as u8);
|
||||
|
|
@ -34,20 +34,22 @@ unsafe fn test_triangle() -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
static PRINT : bool = false;
|
||||
static PRINT: bool = false;
|
||||
|
||||
unsafe fn allocate(layout: Layout) -> *mut u8 {
|
||||
if PRINT {
|
||||
println!("allocate({:?})", layout);
|
||||
}
|
||||
|
||||
let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
let memory = Global
|
||||
.alloc(layout, AllocInit::Uninitialized)
|
||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
|
||||
if PRINT {
|
||||
println!("allocate({:?}) = {:?}", layout, ptr);
|
||||
println!("allocate({:?}) = {:?}", layout, memory.ptr);
|
||||
}
|
||||
|
||||
ptr.cast().as_ptr()
|
||||
memory.ptr.cast().as_ptr()
|
||||
}
|
||||
|
||||
unsafe fn deallocate(ptr: *mut u8, layout: Layout) {
|
||||
|
|
@ -63,19 +65,31 @@ unsafe fn test_triangle() -> bool {
|
|||
println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new);
|
||||
}
|
||||
|
||||
let (ptr, _) = Global.realloc(NonNull::new_unchecked(ptr), old, new.size())
|
||||
.unwrap_or_else(|_| handle_alloc_error(
|
||||
Layout::from_size_align_unchecked(new.size(), old.align())
|
||||
));
|
||||
let memory = if new.size() > old.size() {
|
||||
Global.grow(
|
||||
NonNull::new_unchecked(ptr),
|
||||
old,
|
||||
new.size(),
|
||||
ReallocPlacement::MayMove,
|
||||
AllocInit::Uninitialized,
|
||||
)
|
||||
} else {
|
||||
Global.shrink(NonNull::new_unchecked(ptr), old, new.size(), ReallocPlacement::MayMove)
|
||||
};
|
||||
|
||||
let memory = memory.unwrap_or_else(|_| {
|
||||
handle_alloc_error(Layout::from_size_align_unchecked(new.size(), old.align()))
|
||||
});
|
||||
|
||||
if PRINT {
|
||||
println!("reallocate({:?}, old={:?}, new={:?}) = {:?}",
|
||||
ptr, old, new, ptr);
|
||||
println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", ptr, old, new, memory.ptr);
|
||||
}
|
||||
ptr.cast().as_ptr()
|
||||
memory.ptr.cast().as_ptr()
|
||||
}
|
||||
|
||||
fn idx_to_size(i: usize) -> usize { (i+1) * 10 }
|
||||
fn idx_to_size(i: usize) -> usize {
|
||||
(i + 1) * 10
|
||||
}
|
||||
|
||||
// Allocate pairs of rows that form a triangle shape. (Hope is
|
||||
// that at least two rows will be allocated near each other, so
|
||||
|
|
@ -83,13 +97,13 @@ unsafe fn test_triangle() -> bool {
|
|||
// way.)
|
||||
for i in 0..COUNT / 2 {
|
||||
let size = idx_to_size(i);
|
||||
ascend[2*i] = allocate(Layout::from_size_align(size, ALIGN).unwrap());
|
||||
ascend[2*i+1] = allocate(Layout::from_size_align(size, ALIGN).unwrap());
|
||||
ascend[2 * i] = allocate(Layout::from_size_align(size, ALIGN).unwrap());
|
||||
ascend[2 * i + 1] = allocate(Layout::from_size_align(size, ALIGN).unwrap());
|
||||
}
|
||||
|
||||
// Initialize each pair of rows to distinct value.
|
||||
for i in 0..COUNT / 2 {
|
||||
let (p0, p1, size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
|
||||
let (p0, p1, size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i));
|
||||
for j in 0..size {
|
||||
*p0.add(j) = i as u8;
|
||||
*p1.add(j) = i as u8;
|
||||
|
|
@ -104,8 +118,8 @@ unsafe fn test_triangle() -> bool {
|
|||
|
||||
for i in 0..COUNT / 2 {
|
||||
let size = idx_to_size(i);
|
||||
deallocate(ascend[2*i], Layout::from_size_align(size, ALIGN).unwrap());
|
||||
deallocate(ascend[2*i+1], Layout::from_size_align(size, ALIGN).unwrap());
|
||||
deallocate(ascend[2 * i], Layout::from_size_align(size, ALIGN).unwrap());
|
||||
deallocate(ascend[2 * i + 1], Layout::from_size_align(size, ALIGN).unwrap());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -115,68 +129,68 @@ unsafe fn test_triangle() -> bool {
|
|||
// realloc'ing each row from top to bottom, and checking all the
|
||||
// rows as we go.
|
||||
unsafe fn test_1(ascend: &mut [*mut u8]) {
|
||||
let new_size = idx_to_size(COUNT-1);
|
||||
let new_size = idx_to_size(COUNT - 1);
|
||||
let new = Layout::from_size_align(new_size, ALIGN).unwrap();
|
||||
for i in 0..COUNT / 2 {
|
||||
let (p0, p1, old_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
|
||||
let (p0, p1, old_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i));
|
||||
assert!(old_size < new_size);
|
||||
let old = Layout::from_size_align(old_size, ALIGN).unwrap();
|
||||
|
||||
ascend[2*i] = reallocate(p0, old.clone(), new.clone());
|
||||
ascend[2 * i] = reallocate(p0, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
|
||||
ascend[2*i+1] = reallocate(p1, old.clone(), new.clone());
|
||||
ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 2: turn the square back into a triangle, top to bottom.
|
||||
unsafe fn test_2(ascend: &mut [*mut u8]) {
|
||||
let old_size = idx_to_size(COUNT-1);
|
||||
let old_size = idx_to_size(COUNT - 1);
|
||||
let old = Layout::from_size_align(old_size, ALIGN).unwrap();
|
||||
for i in 0..COUNT / 2 {
|
||||
let (p0, p1, new_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
|
||||
let (p0, p1, new_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i));
|
||||
assert!(new_size < old_size);
|
||||
let new = Layout::from_size_align(new_size, ALIGN).unwrap();
|
||||
|
||||
ascend[2*i] = reallocate(p0, old.clone(), new.clone());
|
||||
ascend[2 * i] = reallocate(p0, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
|
||||
ascend[2*i+1] = reallocate(p1, old.clone(), new.clone());
|
||||
ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 3: turn triangle into a square, bottom to top.
|
||||
unsafe fn test_3(ascend: &mut [*mut u8]) {
|
||||
let new_size = idx_to_size(COUNT-1);
|
||||
let new_size = idx_to_size(COUNT - 1);
|
||||
let new = Layout::from_size_align(new_size, ALIGN).unwrap();
|
||||
for i in (0..COUNT / 2).rev() {
|
||||
let (p0, p1, old_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
|
||||
let (p0, p1, old_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i));
|
||||
assert!(old_size < new_size);
|
||||
let old = Layout::from_size_align(old_size, ALIGN).unwrap();
|
||||
|
||||
ascend[2*i+1] = reallocate(p1, old.clone(), new.clone());
|
||||
ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
|
||||
ascend[2*i] = reallocate(p0, old.clone(), new.clone());
|
||||
ascend[2 * i] = reallocate(p0, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
}
|
||||
}
|
||||
|
||||
// Test 4: turn the square back into a triangle, bottom to top.
|
||||
unsafe fn test_4(ascend: &mut [*mut u8]) {
|
||||
let old_size = idx_to_size(COUNT-1);
|
||||
let old_size = idx_to_size(COUNT - 1);
|
||||
let old = Layout::from_size_align(old_size, ALIGN).unwrap();
|
||||
for i in (0..COUNT / 2).rev() {
|
||||
let (p0, p1, new_size) = (ascend[2*i], ascend[2*i+1], idx_to_size(i));
|
||||
let (p0, p1, new_size) = (ascend[2 * i], ascend[2 * i + 1], idx_to_size(i));
|
||||
assert!(new_size < old_size);
|
||||
let new = Layout::from_size_align(new_size, ALIGN).unwrap();
|
||||
|
||||
ascend[2*i+1] = reallocate(p1, old.clone(), new.clone());
|
||||
ascend[2 * i + 1] = reallocate(p1, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
|
||||
ascend[2*i] = reallocate(p0, old.clone(), new.clone());
|
||||
ascend[2 * i] = reallocate(p0, old.clone(), new.clone());
|
||||
sanity_check(&*ascend);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +1,34 @@
|
|||
// run-pass
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(allocator_api)]
|
||||
|
||||
use std::alloc::{AllocRef, Global, Layout, handle_alloc_error};
|
||||
use std::alloc::{handle_alloc_error, AllocInit, AllocRef, Global, Layout};
|
||||
use std::ptr::NonNull;
|
||||
|
||||
struct arena(());
|
||||
|
||||
struct Bcx<'a> {
|
||||
fcx: &'a Fcx<'a>
|
||||
fcx: &'a Fcx<'a>,
|
||||
}
|
||||
|
||||
struct Fcx<'a> {
|
||||
arena: &'a arena,
|
||||
ccx: &'a Ccx
|
||||
ccx: &'a Ccx,
|
||||
}
|
||||
|
||||
struct Ccx {
|
||||
x: isize
|
||||
x: isize,
|
||||
}
|
||||
|
||||
fn alloc(_bcx: &arena) -> &Bcx<'_> {
|
||||
unsafe {
|
||||
let layout = Layout::new::<Bcx>();
|
||||
let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
&*(ptr.as_ptr() as *const _)
|
||||
let memory = Global
|
||||
.alloc(layout, AllocInit::Uninitialized)
|
||||
.unwrap_or_else(|_| handle_alloc_error(layout));
|
||||
&*(memory.ptr.as_ptr() as *const _)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue