Rollup merge of #73458 - tmiasko:arena-layout, r=matthewjasper

Use alloc::Layout in DroplessArena API
This commit is contained in:
Manish Goregaokar 2020-06-19 19:43:09 -07:00 committed by GitHub
commit fd1c7835a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 32 deletions

View File

@ -22,6 +22,7 @@ extern crate alloc;
use rustc_data_structures::cold_path; use rustc_data_structures::cold_path;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::alloc::Layout;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::cmp; use std::cmp;
use std::intrinsics; use std::intrinsics;
@ -363,13 +364,15 @@ impl DroplessArena {
} }
} }
/// Allocates a byte slice with specified size and alignment from the /// Allocates a byte slice with specified layout from the current memory
/// current memory chunk. Returns `None` if there is no free space left to /// chunk. Returns `None` if there is no free space left to satisfy the
/// satisfy the request. /// request.
#[inline] #[inline]
fn alloc_raw_without_grow(&self, bytes: usize, align: usize) -> Option<*mut u8> { fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> {
let ptr = self.ptr.get() as usize; let ptr = self.ptr.get() as usize;
let end = self.end.get() as usize; let end = self.end.get() as usize;
let align = layout.align();
let bytes = layout.size();
// The allocation request fits into the current chunk iff: // The allocation request fits into the current chunk iff:
// //
// let aligned = align_to(ptr, align); // let aligned = align_to(ptr, align);
@ -390,15 +393,15 @@ impl DroplessArena {
} }
#[inline] #[inline]
pub fn alloc_raw(&self, bytes: usize, align: usize) -> *mut u8 { pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
assert!(bytes != 0); assert!(layout.size() != 0);
loop { loop {
if let Some(a) = self.alloc_raw_without_grow(bytes, align) { if let Some(a) = self.alloc_raw_without_grow(layout) {
break a; break a;
} }
// No free space left. Allocate a new chunk to satisfy the request. // No free space left. Allocate a new chunk to satisfy the request.
// On failure the grow will panic or abort. // On failure the grow will panic or abort.
self.grow(bytes); self.grow(layout.size());
} }
} }
@ -406,7 +409,7 @@ impl DroplessArena {
pub fn alloc<T>(&self, object: T) -> &mut T { pub fn alloc<T>(&self, object: T) -> &mut T {
assert!(!mem::needs_drop::<T>()); assert!(!mem::needs_drop::<T>());
let mem = self.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>()) as *mut T; let mem = self.alloc_raw(Layout::for_value::<T>(&object)) as *mut T;
unsafe { unsafe {
// Write into uninitialized memory. // Write into uninitialized memory.
@ -431,7 +434,7 @@ impl DroplessArena {
assert!(mem::size_of::<T>() != 0); assert!(mem::size_of::<T>() != 0);
assert!(!slice.is_empty()); assert!(!slice.is_empty());
let mem = self.alloc_raw(slice.len() * mem::size_of::<T>(), mem::align_of::<T>()) as *mut T; let mem = self.alloc_raw(Layout::for_value::<[T]>(slice)) as *mut T;
unsafe { unsafe {
mem.copy_from_nonoverlapping(slice.as_ptr(), slice.len()); mem.copy_from_nonoverlapping(slice.as_ptr(), slice.len());
@ -477,8 +480,8 @@ impl DroplessArena {
if len == 0 { if len == 0 {
return &mut []; return &mut [];
} }
let size = len.checked_mul(mem::size_of::<T>()).unwrap();
let mem = self.alloc_raw(size, mem::align_of::<T>()) as *mut T; let mem = self.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;
unsafe { self.write_from_iter(iter, len, mem) } unsafe { self.write_from_iter(iter, len, mem) }
} }
(_, _) => { (_, _) => {
@ -491,9 +494,8 @@ impl DroplessArena {
// the content of the SmallVec // the content of the SmallVec
unsafe { unsafe {
let len = vec.len(); let len = vec.len();
let start_ptr = self let start_ptr =
.alloc_raw(len * mem::size_of::<T>(), mem::align_of::<T>()) self.alloc_raw(Layout::for_value::<[T]>(vec.as_slice())) as *mut T;
as *mut T;
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len); vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
vec.set_len(0); vec.set_len(0);
slice::from_raw_parts_mut(start_ptr, len) slice::from_raw_parts_mut(start_ptr, len)
@ -537,7 +539,7 @@ pub struct DropArena {
impl DropArena { impl DropArena {
#[inline] #[inline]
pub unsafe fn alloc<T>(&self, object: T) -> &mut T { pub unsafe fn alloc<T>(&self, object: T) -> &mut T {
let mem = self.arena.alloc_raw(mem::size_of::<T>(), mem::align_of::<T>()) as *mut T; let mem = self.arena.alloc_raw(Layout::new::<T>()) as *mut T;
// Write into uninitialized memory. // Write into uninitialized memory.
ptr::write(mem, object); ptr::write(mem, object);
let result = &mut *mem; let result = &mut *mem;
@ -557,10 +559,7 @@ impl DropArena {
} }
let len = vec.len(); let len = vec.len();
let start_ptr = self let start_ptr = self.arena.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;
.arena
.alloc_raw(len.checked_mul(mem::size_of::<T>()).unwrap(), mem::align_of::<T>())
as *mut T;
let mut destructors = self.destructors.borrow_mut(); let mut destructors = self.destructors.borrow_mut();
// Reserve space for the destructors so we can't panic while adding them // Reserve space for the destructors so we can't panic while adding them

View File

@ -2,7 +2,8 @@ use crate::arena::Arena;
use rustc_serialize::{Encodable, Encoder}; use rustc_serialize::{Encodable, Encoder};
use std::cmp::{self, Ordering}; use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt; use std::fmt;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::iter; use std::iter;
@ -43,17 +44,9 @@ impl<T: Copy> List<T> {
assert!(mem::size_of::<T>() != 0); assert!(mem::size_of::<T>() != 0);
assert!(!slice.is_empty()); assert!(!slice.is_empty());
// Align up the size of the len (usize) field let (layout, _offset) =
let align = mem::align_of::<T>(); Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
let align_mask = align - 1; let mem = arena.dropless.alloc_raw(layout);
let offset = mem::size_of::<usize>();
let offset = (offset + align_mask) & !align_mask;
let size = offset + slice.len() * mem::size_of::<T>();
let mem = arena
.dropless
.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>()));
unsafe { unsafe {
let result = &mut *(mem as *mut List<T>); let result = &mut *(mem as *mut List<T>);
// Write the length // Write the length