Skip to content

Commit 6a979b3

Browse files
committed
Auto merge of #153108 - alexcrichton:revert, r=joboet
Revert "Simplify internals of `{Rc,Arc}::default`" This reverts #152591 following a [perf run being done](#152591 (comment)). I'm not really positioned at this time to dive in further and understand the performance regressions, so I'll back away from `Rc`/`Arc` and leave them as-is.
2 parents 25396cf + 57d20c1 commit 6a979b3

3 files changed

Lines changed: 24 additions & 42 deletions

File tree

library/alloc/src/rc.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ struct RcInner<T: ?Sized> {
289289
}
290290

291291
/// Calculate layout for `RcInner<T>` using the inner value's layout
292-
#[inline]
293292
fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout {
294293
// Calculate layout using the given value layout.
295294
// Previously, layout was calculated on the expression
@@ -2519,25 +2518,15 @@ impl<T: Default> Default for Rc<T> {
25192518
/// ```
25202519
#[inline]
25212520
fn default() -> Self {
2522-
// First create an uninitialized allocation before creating an instance
2523-
// of `T`. This avoids having `T` on the stack and avoids the need to
2524-
// codegen a call to the destructor for `T` leading to generally better
2525-
// codegen. See #131460 for some more details.
2526-
let mut rc = Rc::new_uninit();
2527-
2528-
// SAFETY: this is a freshly allocated `Rc` so it's guaranteed there are
2529-
// no other strong or weak pointers other than `rc` itself.
25302521
unsafe {
2531-
let raw = Rc::get_mut_unchecked(&mut rc);
2532-
2533-
// Note that `ptr::write` here is used specifically instead of
2534-
// `MaybeUninit::write` to avoid creating an extra stack copy of `T`
2535-
// in debug mode. See #136043 for more context.
2536-
ptr::write(raw.as_mut_ptr(), T::default());
2522+
Self::from_inner(
2523+
Box::leak(Box::write(
2524+
Box::new_uninit(),
2525+
RcInner { strong: Cell::new(1), weak: Cell::new(1), value: T::default() },
2526+
))
2527+
.into(),
2528+
)
25372529
}
2538-
2539-
// SAFETY: this allocation was just initialized above.
2540-
unsafe { rc.assume_init() }
25412530
}
25422531
}
25432532

library/alloc/src/sync.rs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,6 @@ struct ArcInner<T: ?Sized> {
392392
}
393393

394394
/// Calculate layout for `ArcInner<T>` using the inner value's layout
395-
#[inline]
396395
fn arcinner_layout_for_value_layout(layout: Layout) -> Layout {
397396
// Calculate layout using the given value layout.
398397
// Previously, layout was calculated on the expression
@@ -3725,25 +3724,19 @@ impl<T: Default> Default for Arc<T> {
37253724
/// assert_eq!(*x, 0);
37263725
/// ```
37273726
fn default() -> Arc<T> {
3728-
// First create an uninitialized allocation before creating an instance
3729-
// of `T`. This avoids having `T` on the stack and avoids the need to
3730-
// codegen a call to the destructor for `T` leading to generally better
3731-
// codegen. See #131460 for some more details.
3732-
let mut arc = Arc::new_uninit();
3733-
3734-
// SAFETY: this is a freshly allocated `Arc` so it's guaranteed there
3735-
// are no other strong or weak pointers other than `arc` itself.
37363727
unsafe {
3737-
let raw = Arc::get_mut_unchecked(&mut arc);
3738-
3739-
// Note that `ptr::write` here is used specifically instead of
3740-
// `MaybeUninit::write` to avoid creating an extra stack copy of `T`
3741-
// in debug mode. See #136043 for more context.
3742-
ptr::write(raw.as_mut_ptr(), T::default());
3728+
Self::from_inner(
3729+
Box::leak(Box::write(
3730+
Box::new_uninit(),
3731+
ArcInner {
3732+
strong: atomic::AtomicUsize::new(1),
3733+
weak: atomic::AtomicUsize::new(1),
3734+
data: T::default(),
3735+
},
3736+
))
3737+
.into(),
3738+
)
37433739
}
3744-
3745-
// SAFETY: this allocation was just initialized above.
3746-
unsafe { arc.assume_init() }
37473740
}
37483741
}
37493742

tests/codegen-llvm/issues/issue-111603.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,18 @@ use std::sync::Arc;
1010
pub fn new_from_array(x: u64) -> Arc<[u64]> {
1111
// Ensure that we only generate one alloca for the array.
1212

13-
// CHECK: %[[A:.+]] = alloca
13+
// CHECK: alloca
1414
// CHECK-SAME: [8000 x i8]
15-
// CHECK-NOT: %[[B:.+]] = alloca
15+
// CHECK-NOT: alloca
1616
let array = [x; 1000];
1717
Arc::new(array)
1818
}
1919

2020
// CHECK-LABEL: @new_uninit
2121
#[no_mangle]
2222
pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
23-
// CHECK: %[[A:.+]] = alloca
24-
// CHECK-SAME: [8000 x i8]
25-
// CHECK-NOT: %[[B:.+]] = alloca
23+
// CHECK: call alloc::sync::arcinner_layout_for_value_layout
24+
// CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
2625
let mut arc = Arc::new_uninit();
2726
unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]);
2827
unsafe { arc.assume_init() }
@@ -31,7 +30,8 @@ pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> {
3130
// CHECK-LABEL: @new_uninit_slice
3231
#[no_mangle]
3332
pub fn new_uninit_slice(x: u64) -> Arc<[u64]> {
34-
// CHECK-NOT: %[[B:.+]] = alloca
33+
// CHECK: call alloc::sync::arcinner_layout_for_value_layout
34+
// CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout
3535
let mut arc = Arc::new_uninit_slice(1000);
3636
for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } {
3737
elem.write(x);

0 commit comments

Comments
 (0)