Skip to content

Commit f89f30f

Browse files
committed
Move directly when Rc/Arc::make_mut splits from Weak
When only other `Weak` references remain, we can directly move the data into the new unique allocation as a plain memory copy.
1 parent d85df44 commit f89f30f

File tree

2 files changed

+13
-14
lines changed

2 files changed

+13
-14
lines changed

library/alloc/src/rc.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -1048,14 +1048,16 @@ impl<T: Clone> Rc<T> {
10481048
}
10491049
} else if Rc::weak_count(this) != 0 {
10501050
// Can just steal the data, all that's left is Weaks
1051+
let mut rc = Self::new_uninit();
10511052
unsafe {
1052-
let mut swap = Rc::new(ptr::read(&this.ptr.as_ref().value));
1053-
mem::swap(this, &mut swap);
1054-
swap.inner().dec_strong();
1053+
let data = Rc::get_mut_unchecked(&mut rc);
1054+
data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
1055+
1056+
this.inner().dec_strong();
10551057
// Remove implicit strong-weak ref (no need to craft a fake
10561058
// Weak here -- we know other Weaks can clean up for us)
1057-
swap.inner().dec_weak();
1058-
forget(swap);
1059+
this.inner().dec_weak();
1060+
ptr::write(this, rc.assume_init());
10591061
}
10601062
}
10611063
// This unsafety is ok because we're guaranteed that the pointer

library/alloc/src/sync.rs

+6-9
Original file line numberDiff line numberDiff line change
@@ -1392,17 +1392,14 @@ impl<T: Clone> Arc<T> {
13921392

13931393
// Materialize our own implicit weak pointer, so that it can clean
13941394
// up the ArcInner as needed.
1395-
let weak = Weak { ptr: this.ptr };
1395+
let _weak = Weak { ptr: this.ptr };
13961396

1397-
// mark the data itself as already deallocated
1397+
// Can just steal the data, all that's left is Weaks
1398+
let mut arc = Self::new_uninit();
13981399
unsafe {
1399-
// there is no data race in the implicit write caused by `read`
1400-
// here (due to zeroing) because data is no longer accessed by
1401-
// other threads (due to there being no more strong refs at this
1402-
// point).
1403-
let mut swap = Arc::new(ptr::read(&weak.ptr.as_ref().data));
1404-
mem::swap(this, &mut swap);
1405-
mem::forget(swap);
1400+
let data = Arc::get_mut_unchecked(&mut arc);
1401+
data.as_mut_ptr().copy_from_nonoverlapping(&**this, 1);
1402+
ptr::write(this, arc.assume_init());
14061403
}
14071404
} else {
14081405
// We were the sole reference of either kind; bump back up the

0 commit comments

Comments
 (0)