Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use alloc::Layout in DroplessArena API #73458

Merged
merged 1 commit into from
Jun 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 19 additions & 20 deletions src/librustc_arena/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extern crate alloc;
use rustc_data_structures::cold_path;
use smallvec::SmallVec;

use std::alloc::Layout;
use std::cell::{Cell, RefCell};
use std::cmp;
use std::intrinsics;
Expand Down Expand Up @@ -363,13 +364,15 @@ impl DroplessArena {
}
}

/// Allocates a byte slice with specified size and alignment from the
/// current memory chunk. Returns `None` if there is no free space left to
/// satisfy the request.
/// Allocates a byte slice with specified layout from the current memory
/// chunk. Returns `None` if there is no free space left to satisfy the
/// request.
#[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 end = self.end.get() as usize;
let align = layout.align();
let bytes = layout.size();
// The allocation request fits into the current chunk iff:
//
// let aligned = align_to(ptr, align);
Expand All @@ -390,23 +393,23 @@ impl DroplessArena {
}

#[inline]
pub fn alloc_raw(&self, bytes: usize, align: usize) -> *mut u8 {
assert!(bytes != 0);
pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
assert!(layout.size() != 0);
loop {
if let Some(a) = self.alloc_raw_without_grow(bytes, align) {
if let Some(a) = self.alloc_raw_without_grow(layout) {
break a;
}
// No free space left. Allocate a new chunk to satisfy the request.
// On failure the grow will panic or abort.
self.grow(bytes);
self.grow(layout.size());
}
}

#[inline]
pub fn alloc<T>(&self, object: T) -> &mut 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 {
// Write into uninitialized memory.
Expand All @@ -431,7 +434,7 @@ impl DroplessArena {
assert!(mem::size_of::<T>() != 0);
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 {
mem.copy_from_nonoverlapping(slice.as_ptr(), slice.len());
Expand Down Expand Up @@ -477,8 +480,8 @@ impl DroplessArena {
if len == 0 {
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) }
}
(_, _) => {
Expand All @@ -491,9 +494,8 @@ impl DroplessArena {
// the content of the SmallVec
unsafe {
let len = vec.len();
let start_ptr = self
.alloc_raw(len * mem::size_of::<T>(), mem::align_of::<T>())
as *mut T;
let start_ptr =
self.alloc_raw(Layout::for_value::<[T]>(vec.as_slice())) as *mut T;
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
vec.set_len(0);
slice::from_raw_parts_mut(start_ptr, len)
Expand Down Expand Up @@ -537,7 +539,7 @@ pub struct DropArena {
impl DropArena {
#[inline]
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.
ptr::write(mem, object);
let result = &mut *mem;
Expand All @@ -557,10 +559,7 @@ impl DropArena {
}
let len = vec.len();

let start_ptr = self
.arena
.alloc_raw(len.checked_mul(mem::size_of::<T>()).unwrap(), mem::align_of::<T>())
as *mut T;
let start_ptr = self.arena.alloc_raw(Layout::array::<T>(len).unwrap()) as *mut T;

let mut destructors = self.destructors.borrow_mut();
// Reserve space for the destructors so we can't panic while adding them
Expand Down
17 changes: 5 additions & 12 deletions src/librustc_middle/ty/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use crate::arena::Arena;

use rustc_serialize::{Encodable, Encoder};

use std::cmp::{self, Ordering};
use std::alloc::Layout;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter;
Expand Down Expand Up @@ -43,17 +44,9 @@ impl<T: Copy> List<T> {
assert!(mem::size_of::<T>() != 0);
assert!(!slice.is_empty());

// Align up the size of the len (usize) field
let align = mem::align_of::<T>();
let align_mask = align - 1;
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>()));
let (layout, _offset) =
Layout::new::<usize>().extend(Layout::for_value::<[T]>(slice)).unwrap();
let mem = arena.dropless.alloc_raw(layout);
unsafe {
let result = &mut *(mem as *mut List<T>);
// Write the length
Expand Down