Skip to content

Commit 0eb6753

Browse files
authored
Rollup merge of #93365 - nnethercote:more-arena-cleanups, r=oli-obk
More arena cleanups A sequel to #90990. r? `@oli-obk`
2 parents 8347f78 + 6035487 commit 0eb6753

File tree

1 file changed

+40
-21
lines changed
  • compiler/rustc_arena/src

1 file changed

+40
-21
lines changed

Diff for: compiler/rustc_arena/src/lib.rs

+40-21
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,24 @@ pub struct TypedArena<T> {
4545
end: Cell<*mut T>,
4646

4747
/// A vector of arena chunks.
48-
chunks: RefCell<Vec<TypedArenaChunk<T>>>,
48+
chunks: RefCell<Vec<ArenaChunk<T>>>,
4949

5050
/// Marker indicating that dropping the arena causes its owned
5151
/// instances of `T` to be dropped.
5252
_own: PhantomData<T>,
5353
}
5454

55-
struct TypedArenaChunk<T> {
55+
struct ArenaChunk<T = u8> {
5656
/// The raw storage for the arena chunk.
5757
storage: Box<[MaybeUninit<T>]>,
5858
/// The number of valid entries in the chunk.
5959
entries: usize,
6060
}
6161

62-
impl<T> TypedArenaChunk<T> {
62+
impl<T> ArenaChunk<T> {
6363
#[inline]
64-
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
65-
TypedArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
64+
unsafe fn new(capacity: usize) -> ArenaChunk<T> {
65+
ArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
6666
}
6767

6868
/// Destroys this arena chunk.
@@ -125,6 +125,11 @@ impl<I, T> IterExt<T> for I
125125
where
126126
I: IntoIterator<Item = T>,
127127
{
128+
// This default collects into a `SmallVec` and then allocates by copying
129+
// from it. The specializations below for types like `Vec` are more
130+
// efficient, copying directly without the intermediate collecting step.
131+
// This default could be made more efficient, like
132+
// `DroplessArena::alloc_from_iter`, but it's not hot enough to bother.
128133
#[inline]
129134
default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
130135
let vec: SmallVec<[_; 8]> = self.into_iter().collect();
@@ -139,7 +144,7 @@ impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> {
139144
if len == 0 {
140145
return &mut [];
141146
}
142-
// Move the content to the arena by copying and then forgetting it
147+
// Move the content to the arena by copying and then forgetting it.
143148
unsafe {
144149
let start_ptr = arena.alloc_raw_slice(len);
145150
self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
@@ -156,7 +161,7 @@ impl<T> IterExt<T> for Vec<T> {
156161
if len == 0 {
157162
return &mut [];
158163
}
159-
// Move the content to the arena by copying and then forgetting it
164+
// Move the content to the arena by copying and then forgetting it.
160165
unsafe {
161166
let start_ptr = arena.alloc_raw_slice(len);
162167
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
@@ -173,7 +178,7 @@ impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> {
173178
if len == 0 {
174179
return &mut [];
175180
}
176-
// Move the content to the arena by copying and then forgetting it
181+
// Move the content to the arena by copying and then forgetting it.
177182
unsafe {
178183
let start_ptr = arena.alloc_raw_slice(len);
179184
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
@@ -272,7 +277,7 @@ impl<T> TypedArena<T> {
272277
// Also ensure that this chunk can fit `additional`.
273278
new_cap = cmp::max(additional, new_cap);
274279

275-
let mut chunk = TypedArenaChunk::<T>::new(new_cap);
280+
let mut chunk = ArenaChunk::<T>::new(new_cap);
276281
self.ptr.set(chunk.start());
277282
self.end.set(chunk.end());
278283
chunks.push(chunk);
@@ -281,7 +286,7 @@ impl<T> TypedArena<T> {
281286

282287
// Drops the contents of the last chunk. The last chunk is partially empty, unlike all other
283288
// chunks.
284-
fn clear_last_chunk(&self, last_chunk: &mut TypedArenaChunk<T>) {
289+
fn clear_last_chunk(&self, last_chunk: &mut ArenaChunk<T>) {
285290
// Determine how much was filled.
286291
let start = last_chunk.start() as usize;
287292
// We obtain the value of the pointer to the first uninitialized element.
@@ -340,7 +345,7 @@ pub struct DroplessArena {
340345
end: Cell<*mut u8>,
341346

342347
/// A vector of arena chunks.
343-
chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
348+
chunks: RefCell<Vec<ArenaChunk>>,
344349
}
345350

346351
unsafe impl Send for DroplessArena {}
@@ -378,7 +383,7 @@ impl DroplessArena {
378383
// Also ensure that this chunk can fit `additional`.
379384
new_cap = cmp::max(additional, new_cap);
380385

381-
let mut chunk = TypedArenaChunk::<u8>::new(new_cap);
386+
let mut chunk = ArenaChunk::new(new_cap);
382387
self.start.set(chunk.start());
383388
self.end.set(chunk.end());
384389
chunks.push(chunk);
@@ -520,10 +525,19 @@ impl DroplessArena {
520525
}
521526
}
522527

523-
// Declare an `Arena` containing one dropless arena and many typed arenas (the
524-
// types of the typed arenas are specified by the arguments). The dropless
525-
// arena will be used for any types that impl `Copy`, and also for any of the
526-
// specified types that satisfy `!mem::needs_drop`.
528+
/// Declare an `Arena` containing one dropless arena and many typed arenas (the
529+
/// types of the typed arenas are specified by the arguments).
530+
///
531+
/// There are three cases of interest.
532+
/// - Types that are `Copy`: these need not be specified in the arguments. They
533+
/// will use the `DroplessArena`.
534+
/// - Types that are `!Copy` and `!Drop`: these must be specified in the
535+
/// arguments. An empty `TypedArena` will be created for each one, but the
536+
/// `DroplessArena` will always be used and the `TypedArena` will stay empty.
537+
/// This is odd but harmless, because an empty arena allocates no memory.
538+
/// - Types that are `!Copy` and `Drop`: these must be specified in the
539+
/// arguments. The `TypedArena` will be used for them.
540+
///
527541
#[rustc_macro_transparency = "semitransparent"]
528542
pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
529543
#[derive(Default)]
@@ -532,7 +546,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
532546
$($name: $crate::TypedArena<$ty>,)*
533547
}
534548

535-
pub trait ArenaAllocatable<'tcx, T = Self>: Sized {
549+
pub trait ArenaAllocatable<'tcx, C = rustc_arena::IsNotCopy>: Sized {
536550
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self;
537551
fn allocate_from_iter<'a>(
538552
arena: &'a Arena<'tcx>,
@@ -541,7 +555,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
541555
}
542556

543557
// Any type that impls `Copy` can be arena-allocated in the `DroplessArena`.
544-
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, ()> for T {
558+
impl<'tcx, T: Copy> ArenaAllocatable<'tcx, rustc_arena::IsCopy> for T {
545559
#[inline]
546560
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
547561
arena.dropless.alloc(self)
@@ -555,7 +569,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
555569
}
556570
}
557571
$(
558-
impl<'tcx> ArenaAllocatable<'tcx, $ty> for $ty {
572+
impl<'tcx> ArenaAllocatable<'tcx, rustc_arena::IsNotCopy> for $ty {
559573
#[inline]
560574
fn allocate_on<'a>(self, arena: &'a Arena<'tcx>) -> &'a mut Self {
561575
if !::std::mem::needs_drop::<Self>() {
@@ -581,7 +595,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
581595

582596
impl<'tcx> Arena<'tcx> {
583597
#[inline]
584-
pub fn alloc<T: ArenaAllocatable<'tcx, U>, U>(&self, value: T) -> &mut T {
598+
pub fn alloc<T: ArenaAllocatable<'tcx, C>, C>(&self, value: T) -> &mut T {
585599
value.allocate_on(self)
586600
}
587601

@@ -594,7 +608,7 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
594608
self.dropless.alloc_slice(value)
595609
}
596610

597-
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, U>, U>(
611+
pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, C>, C>(
598612
&'a self,
599613
iter: impl ::std::iter::IntoIterator<Item = T>,
600614
) -> &'a mut [T] {
@@ -603,5 +617,10 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
603617
}
604618
}
605619

620+
// Marker types that let us give different behaviour for arenas allocating
621+
// `Copy` types vs `!Copy` types.
622+
pub struct IsCopy;
623+
pub struct IsNotCopy;
624+
606625
#[cfg(test)]
607626
mod tests;

0 commit comments

Comments
 (0)