Skip to content
Open
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
20 changes: 13 additions & 7 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ struct RcInner<T: ?Sized> {
}

/// Calculate layout for `RcInner<T>` using the inner value's layout
#[inline]
fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout {
// Calculate layout using the given value layout.
// Previously, layout was calculated on the expression
Expand Down Expand Up @@ -2518,15 +2519,20 @@ impl<T: Default> Default for Rc<T> {
/// ```
#[inline]
fn default() -> Self {
// First create an uninitialized allocation before creating an instance
// of `T`. This avoids having `T` on the stack and avoids the need to
// codegen a call to the destructor for `T` leading to generally better
// codegen. See #131460 for some more details.
let mut rc = Rc::new_uninit();

// SAFETY: this is a freshly allocated `Rc` so it's guaranteed there are
// no other strong or weak pointers other than `rc` itself.
unsafe {
Self::from_inner(
Box::leak(Box::write(
Box::new_uninit(),
RcInner { strong: Cell::new(1), weak: Cell::new(1), value: T::default() },
))
.into(),
)
Rc::get_mut_unchecked(&mut rc).write(T::default());
}

// SAFETY: this allocation was just initialized above.
unsafe { rc.assume_init() }
}
}

Expand Down
24 changes: 13 additions & 11 deletions library/alloc/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ struct ArcInner<T: ?Sized> {
}

/// Calculate layout for `ArcInner<T>` using the inner value's layout
#[inline]
fn arcinner_layout_for_value_layout(layout: Layout) -> Layout {
// Calculate layout using the given value layout.
// Previously, layout was calculated on the expression
Expand Down Expand Up @@ -3724,19 +3725,20 @@ impl<T: Default> Default for Arc<T> {
/// assert_eq!(*x, 0);
/// ```
fn default() -> Arc<T> {
// First create an uninitialized allocation before creating an instance
// of `T`. This avoids having `T` on the stack and avoids the need to
// codegen a call to the destructor for `T` leading to generally better
// codegen. See #131460 for some more details.
let mut arc = Arc::new_uninit();

// SAFETY: this is a freshly allocated `Arc` so it's guaranteed there
// are no other strong or weak pointers other than `arc` itself.
unsafe {
Self::from_inner(
Box::leak(Box::write(
Box::new_uninit(),
ArcInner {
strong: atomic::AtomicUsize::new(1),
weak: atomic::AtomicUsize::new(1),
data: T::default(),
},
))
.into(),
)
Arc::get_mut_unchecked(&mut arc).write(T::default());
}

// SAFETY: this allocation was just initialized above.
unsafe { arc.assume_init() }
}
}

Expand Down
12 changes: 6 additions & 6 deletions tests/codegen-llvm/issues/issue-111603.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@ use std::sync::Arc;
pub fn new_from_array(x: u64) -> Arc<[u64]> {
// Ensure that we only generate one alloca for the array.

// CHECK: alloca
// CHECK: %[[A:.+]] = alloca
// CHECK-SAME: [8000 x i8]
// CHECK-NOT: alloca
// CHECK-NOT: %[[B:.+]] = alloca
let array = [x; 1000];
Arc::new(array)
}

// CHECK-LABEL: @new_uninit
#[no_mangle]
pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
// CHECK: call alloc::sync::arcinner_layout_for_value_layout
// CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
// CHECK: %[[A:.+]] = alloca
// CHECK-SAME: [8000 x i8]
// CHECK-NOT: %[[B:.+]] = alloca
let mut arc = Arc::new_uninit();
unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]);
unsafe { arc.assume_init() }
Expand All @@ -30,8 +31,7 @@ pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
// CHECK-LABEL: @new_uninit_slice
#[no_mangle]
pub fn new_uninit_slice(x: u64) -> Arc<[u64]> {
// CHECK: call alloc::sync::arcinner_layout_for_value_layout
// CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
// CHECK-NOT: %[[B:.+]] = alloca
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The breadcrumbs for this codegen test points back at #111634 which had to do with internal refactorings about how methods were done. I don't believe that these codegen tests are really all that applicable any more so I did my best to at least keep them somewhat, but the extra #[inline] in this PR effectively means that the internals this test relies on also changed which means that the test needed an update one way or another.

let mut arc = Arc::new_uninit_slice(1000);
for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } {
elem.write(x);
Expand Down
Loading