Skip to content

Commit ad609b9

Browse files
committed
Add #[inline] markers throughout Rc and Arc for performance
Some preliminary testing indicated that there are potential gains to be made with `Rc` and `Arc`. Add `#[inline]`s to help improve performance.
1 parent 1fe3846 commit ad609b9

File tree

2 files changed

+84
-50
lines changed

2 files changed

+84
-50
lines changed

library/alloc/src/rc.rs

Lines changed: 44 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ struct RcBox<T: ?Sized> {
292292
}
293293

294294
/// Calculate layout for `RcBox<T>` using the inner value's layout
295+
#[inline]
295296
fn rcbox_layout_for_value_layout(layout: Layout) -> Layout {
296297
// Calculate layout using the given value layout.
297298
// Previously, layout was calculated on the expression
@@ -385,6 +386,7 @@ impl<T> Rc<T> {
385386
///
386387
/// let five = Rc::new(5);
387388
/// ```
389+
#[inline]
388390
#[cfg(not(no_global_oom_handling))]
389391
#[stable(feature = "rust1", since = "1.0.0")]
390392
pub fn new(value: T) -> Rc<T> {
@@ -514,9 +516,10 @@ impl<T> Rc<T> {
514516
///
515517
/// assert_eq!(*five, 5)
516518
/// ```
519+
#[inline]
520+
#[must_use]
517521
#[cfg(not(no_global_oom_handling))]
518522
#[unstable(feature = "new_uninit", issue = "63291")]
519-
#[must_use]
520523
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
521524
unsafe {
522525
Rc::from_ptr(Rc::allocate_for_layout(
@@ -547,9 +550,10 @@ impl<T> Rc<T> {
547550
/// ```
548551
///
549552
/// [zeroed]: mem::MaybeUninit::zeroed
553+
#[inline]
554+
#[must_use]
550555
#[cfg(not(no_global_oom_handling))]
551556
#[unstable(feature = "new_uninit", issue = "63291")]
552-
#[must_use]
553557
pub fn new_zeroed() -> Rc<mem::MaybeUninit<T>> {
554558
unsafe {
555559
Rc::from_ptr(Rc::allocate_for_layout(
@@ -571,6 +575,7 @@ impl<T> Rc<T> {
571575
/// let five = Rc::try_new(5);
572576
/// # Ok::<(), std::alloc::AllocError>(())
573577
/// ```
578+
#[inline]
574579
#[unstable(feature = "allocator_api", issue = "32838")]
575580
pub fn try_new(value: T) -> Result<Rc<T>, AllocError> {
576581
// There is an implicit weak pointer owned by all the strong
@@ -605,6 +610,7 @@ impl<T> Rc<T> {
605610
/// assert_eq!(*five, 5);
606611
/// # Ok::<(), std::alloc::AllocError>(())
607612
/// ```
613+
#[inline]
608614
#[unstable(feature = "allocator_api", issue = "32838")]
609615
// #[unstable(feature = "new_uninit", issue = "63291")]
610616
pub fn try_new_uninit() -> Result<Rc<mem::MaybeUninit<T>>, AllocError> {
@@ -638,6 +644,7 @@ impl<T> Rc<T> {
638644
/// ```
639645
///
640646
/// [zeroed]: mem::MaybeUninit::zeroed
647+
#[inline]
641648
#[unstable(feature = "allocator_api", issue = "32838")]
642649
//#[unstable(feature = "new_uninit", issue = "63291")]
643650
pub fn try_new_zeroed() -> Result<Rc<mem::MaybeUninit<T>>, AllocError> {
@@ -651,9 +658,10 @@ impl<T> Rc<T> {
651658
}
652659
/// Constructs a new `Pin<Rc<T>>`. If `T` does not implement `Unpin`, then
653660
/// `value` will be pinned in memory and unable to be moved.
661+
#[inline]
662+
#[must_use]
654663
#[cfg(not(no_global_oom_handling))]
655664
#[stable(feature = "pin", since = "1.33.0")]
656-
#[must_use]
657665
pub fn pin(value: T) -> Pin<Rc<T>> {
658666
unsafe { Pin::new_unchecked(Rc::new(value)) }
659667
}
@@ -681,9 +689,9 @@ impl<T, A: Allocator> Rc<T, A> {
681689
///
682690
/// let five = Rc::new_in(5, System);
683691
/// ```
692+
#[inline]
684693
#[cfg(not(no_global_oom_handling))]
685694
#[unstable(feature = "allocator_api", issue = "32838")]
686-
#[inline]
687695
pub fn new_in(value: T, alloc: A) -> Rc<T, A> {
688696
// NOTE: Prefer match over unwrap_or_else since closure sometimes not inlineable.
689697
// That would make code size bigger.
@@ -716,10 +724,10 @@ impl<T, A: Allocator> Rc<T, A> {
716724
///
717725
/// assert_eq!(*five, 5)
718726
/// ```
727+
#[inline]
719728
#[cfg(not(no_global_oom_handling))]
720729
#[unstable(feature = "allocator_api", issue = "32838")]
721730
// #[unstable(feature = "new_uninit", issue = "63291")]
722-
#[inline]
723731
pub fn new_uninit_in(alloc: A) -> Rc<mem::MaybeUninit<T>, A> {
724732
unsafe {
725733
Rc::from_ptr_in(
@@ -755,10 +763,10 @@ impl<T, A: Allocator> Rc<T, A> {
755763
/// ```
756764
///
757765
/// [zeroed]: mem::MaybeUninit::zeroed
766+
#[inline]
758767
#[cfg(not(no_global_oom_handling))]
759768
#[unstable(feature = "allocator_api", issue = "32838")]
760769
// #[unstable(feature = "new_uninit", issue = "63291")]
761-
#[inline]
762770
pub fn new_zeroed_in(alloc: A) -> Rc<mem::MaybeUninit<T>, A> {
763771
unsafe {
764772
Rc::from_ptr_in(
@@ -785,8 +793,8 @@ impl<T, A: Allocator> Rc<T, A> {
785793
/// let five = Rc::try_new_in(5, System);
786794
/// # Ok::<(), std::alloc::AllocError>(())
787795
/// ```
788-
#[unstable(feature = "allocator_api", issue = "32838")]
789796
#[inline]
797+
#[unstable(feature = "allocator_api", issue = "32838")]
790798
pub fn try_new_in(value: T, alloc: A) -> Result<Self, AllocError> {
791799
// There is an implicit weak pointer owned by all the strong
792800
// pointers, which ensures that the weak destructor never frees
@@ -823,9 +831,9 @@ impl<T, A: Allocator> Rc<T, A> {
823831
/// assert_eq!(*five, 5);
824832
/// # Ok::<(), std::alloc::AllocError>(())
825833
/// ```
834+
#[inline]
826835
#[unstable(feature = "allocator_api", issue = "32838")]
827836
// #[unstable(feature = "new_uninit", issue = "63291")]
828-
#[inline]
829837
pub fn try_new_uninit_in(alloc: A) -> Result<Rc<mem::MaybeUninit<T>, A>, AllocError> {
830838
unsafe {
831839
Ok(Rc::from_ptr_in(
@@ -862,9 +870,9 @@ impl<T, A: Allocator> Rc<T, A> {
862870
/// ```
863871
///
864872
/// [zeroed]: mem::MaybeUninit::zeroed
873+
#[inline]
865874
#[unstable(feature = "allocator_api", issue = "32838")]
866875
//#[unstable(feature = "new_uninit", issue = "63291")]
867-
#[inline]
868876
pub fn try_new_zeroed_in(alloc: A) -> Result<Rc<mem::MaybeUninit<T>, A>, AllocError> {
869877
unsafe {
870878
Ok(Rc::from_ptr_in(
@@ -880,9 +888,9 @@ impl<T, A: Allocator> Rc<T, A> {
880888

881889
/// Constructs a new `Pin<Rc<T>>` in the provided allocator. If `T` does not implement `Unpin`, then
882890
/// `value` will be pinned in memory and unable to be moved.
891+
#[inline]
883892
#[cfg(not(no_global_oom_handling))]
884893
#[unstable(feature = "allocator_api", issue = "32838")]
885-
#[inline]
886894
pub fn pin_in(value: T, alloc: A) -> Pin<Self> {
887895
unsafe { Pin::new_unchecked(Rc::new_in(value, alloc)) }
888896
}
@@ -970,9 +978,10 @@ impl<T> Rc<[T]> {
970978
///
971979
/// assert_eq!(*values, [1, 2, 3])
972980
/// ```
981+
#[inline]
982+
#[must_use]
973983
#[cfg(not(no_global_oom_handling))]
974984
#[unstable(feature = "new_uninit", issue = "63291")]
975-
#[must_use]
976985
pub fn new_uninit_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
977986
unsafe { Rc::from_ptr(Rc::allocate_for_slice(len)) }
978987
}
@@ -997,9 +1006,10 @@ impl<T> Rc<[T]> {
9971006
/// ```
9981007
///
9991008
/// [zeroed]: mem::MaybeUninit::zeroed
1009+
#[inline]
1010+
#[must_use]
10001011
#[cfg(not(no_global_oom_handling))]
10011012
#[unstable(feature = "new_uninit", issue = "63291")]
1002-
#[must_use]
10031013
pub fn new_zeroed_slice(len: usize) -> Rc<[mem::MaybeUninit<T>]> {
10041014
unsafe {
10051015
Rc::from_ptr(Rc::allocate_for_layout(
@@ -1040,10 +1050,10 @@ impl<T, A: Allocator> Rc<[T], A> {
10401050
///
10411051
/// assert_eq!(*values, [1, 2, 3])
10421052
/// ```
1053+
#[inline]
10431054
#[cfg(not(no_global_oom_handling))]
10441055
#[unstable(feature = "allocator_api", issue = "32838")]
10451056
// #[unstable(feature = "new_uninit", issue = "63291")]
1046-
#[inline]
10471057
pub fn new_uninit_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit<T>], A> {
10481058
unsafe { Rc::from_ptr_in(Rc::allocate_for_slice_in(len, &alloc), alloc) }
10491059
}
@@ -1070,10 +1080,10 @@ impl<T, A: Allocator> Rc<[T], A> {
10701080
/// ```
10711081
///
10721082
/// [zeroed]: mem::MaybeUninit::zeroed
1083+
#[inline]
10731084
#[cfg(not(no_global_oom_handling))]
10741085
#[unstable(feature = "allocator_api", issue = "32838")]
10751086
// #[unstable(feature = "new_uninit", issue = "63291")]
1076-
#[inline]
10771087
pub fn new_zeroed_slice_in(len: usize, alloc: A) -> Rc<[mem::MaybeUninit<T>], A> {
10781088
unsafe {
10791089
Rc::from_ptr_in(
@@ -1121,8 +1131,8 @@ impl<T, A: Allocator> Rc<mem::MaybeUninit<T>, A> {
11211131
///
11221132
/// assert_eq!(*five, 5)
11231133
/// ```
1124-
#[unstable(feature = "new_uninit", issue = "63291")]
11251134
#[inline]
1135+
#[unstable(feature = "new_uninit", issue = "63291")]
11261136
pub unsafe fn assume_init(self) -> Rc<T, A>
11271137
where
11281138
A: Clone,
@@ -1165,8 +1175,8 @@ impl<T, A: Allocator> Rc<[mem::MaybeUninit<T>], A> {
11651175
///
11661176
/// assert_eq!(*values, [1, 2, 3])
11671177
/// ```
1168-
#[unstable(feature = "new_uninit", issue = "63291")]
11691178
#[inline]
1179+
#[unstable(feature = "new_uninit", issue = "63291")]
11701180
pub unsafe fn assume_init(self) -> Rc<[T], A>
11711181
where
11721182
A: Clone,
@@ -1303,6 +1313,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
13031313
/// let x_ptr = Rc::into_raw(x);
13041314
/// assert_eq!(unsafe { &*x_ptr }, "hello");
13051315
/// ```
1316+
#[inline]
13061317
#[stable(feature = "rc_raw", since = "1.17.0")]
13071318
pub fn into_raw(this: Self) -> *const T {
13081319
let ptr = Self::as_ptr(&this);
@@ -1326,6 +1337,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
13261337
/// assert_eq!(x_ptr, Rc::as_ptr(&y));
13271338
/// assert_eq!(unsafe { &*x_ptr }, "hello");
13281339
/// ```
1340+
#[inline]
13291341
#[stable(feature = "weak_into_raw", since = "1.45.0")]
13301342
pub fn as_ptr(this: &Self) -> *const T {
13311343
let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr);
@@ -1352,7 +1364,8 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
13521364
/// dropped once.
13531365
///
13541366
/// This function is unsafe because improper use may lead to memory unsafety,
1355-
/// even if the returned `Rc<T>` is never accessed.
1367+
/// even if the returned `Rc<T>` is never accessed. The pointer must point to
1368+
/// a region of memory allocated by `alloc`.
13561369
///
13571370
/// [into_raw]: Rc::into_raw
13581371
///
@@ -1377,6 +1390,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
13771390
///
13781391
/// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!
13791392
/// ```
1393+
#[inline]
13801394
#[unstable(feature = "allocator_api", issue = "32838")]
13811395
pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self {
13821396
let offset = unsafe { data_offset(ptr) };
@@ -1398,6 +1412,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
13981412
///
13991413
/// let weak_five = Rc::downgrade(&five);
14001414
/// ```
1415+
#[inline]
14011416
#[must_use = "this returns a new `Weak` pointer, \
14021417
without modifying the original `Rc`"]
14031418
#[stable(feature = "rc_weak", since = "1.4.0")]
@@ -1629,8 +1644,6 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
16291644
unsafe { &mut (*this.ptr.as_ptr()).value }
16301645
}
16311646

1632-
#[inline]
1633-
#[stable(feature = "ptr_eq", since = "1.17.0")]
16341647
/// Returns `true` if the two `Rc`s point to the same allocation in a vein similar to
16351648
/// [`ptr::eq`]. This function ignores the metadata of `dyn Trait` pointers.
16361649
///
@@ -1646,6 +1659,8 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
16461659
/// assert!(Rc::ptr_eq(&five, &same_five));
16471660
/// assert!(!Rc::ptr_eq(&five, &other_five));
16481661
/// ```
1662+
#[inline]
1663+
#[stable(feature = "ptr_eq", since = "1.17.0")]
16491664
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
16501665
this.ptr.as_ptr() as *const () == other.ptr.as_ptr() as *const ()
16511666
}
@@ -1702,8 +1717,8 @@ impl<T: Clone, A: Allocator + Clone> Rc<T, A> {
17021717
/// assert!(76 == *data);
17031718
/// assert!(weak.upgrade().is_none());
17041719
/// ```
1705-
#[cfg(not(no_global_oom_handling))]
17061720
#[inline]
1721+
#[cfg(not(no_global_oom_handling))]
17071722
#[stable(feature = "rc_unique", since = "1.4.0")]
17081723
pub fn make_mut(this: &mut Self) -> &mut T {
17091724
if Rc::strong_count(this) != 1 {
@@ -1851,6 +1866,7 @@ impl<T: ?Sized> Rc<T> {
18511866
///
18521867
/// The function `mem_to_rcbox` is called with the data pointer
18531868
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
1869+
#[inline]
18541870
#[cfg(not(no_global_oom_handling))]
18551871
unsafe fn allocate_for_layout(
18561872
value_layout: Layout,
@@ -2275,7 +2291,7 @@ impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Rc<T, A> {
22752291
///
22762292
/// assert!(five < Rc::new(6));
22772293
/// ```
2278-
#[inline(always)]
2294+
#[inline]
22792295
fn lt(&self, other: &Rc<T, A>) -> bool {
22802296
**self < **other
22812297
}
@@ -2293,7 +2309,7 @@ impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Rc<T, A> {
22932309
///
22942310
/// assert!(five <= Rc::new(5));
22952311
/// ```
2296-
#[inline(always)]
2312+
#[inline]
22972313
fn le(&self, other: &Rc<T, A>) -> bool {
22982314
**self <= **other
22992315
}
@@ -2311,7 +2327,7 @@ impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Rc<T, A> {
23112327
///
23122328
/// assert!(five > Rc::new(4));
23132329
/// ```
2314-
#[inline(always)]
2330+
#[inline]
23152331
fn gt(&self, other: &Rc<T, A>) -> bool {
23162332
**self > **other
23172333
}
@@ -2329,7 +2345,7 @@ impl<T: ?Sized + PartialOrd, A: Allocator> PartialOrd for Rc<T, A> {
23292345
///
23302346
/// assert!(five >= Rc::new(5));
23312347
/// ```
2332-
#[inline(always)]
2348+
#[inline]
23332349
fn ge(&self, other: &Rc<T, A>) -> bool {
23342350
**self >= **other
23352351
}
@@ -2718,9 +2734,9 @@ impl<T> Weak<T> {
27182734
/// assert!(empty.upgrade().is_none());
27192735
/// ```
27202736
#[inline]
2737+
#[must_use]
27212738
#[stable(feature = "downgraded_weak", since = "1.10.0")]
27222739
#[rustc_const_stable(feature = "const_weak_new", since = "CURRENT_RUSTC_VERSION")]
2723-
#[must_use]
27242740
pub const fn new() -> Weak<T> {
27252741
Weak {
27262742
ptr: unsafe { NonNull::new_unchecked(ptr::invalid_mut::<RcBox<T>>(usize::MAX)) },
@@ -2841,6 +2857,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
28412857
/// ```
28422858
///
28432859
/// [`null`]: ptr::null
2860+
#[inline]
28442861
#[must_use]
28452862
#[stable(feature = "rc_as_ptr", since = "1.45.0")]
28462863
pub fn as_ptr(&self) -> *const T {
@@ -2885,6 +2902,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
28852902
///
28862903
/// [`from_raw`]: Weak::from_raw
28872904
/// [`as_ptr`]: Weak::as_ptr
2905+
#[inline]
28882906
#[must_use = "`self` will be dropped if the result is not used"]
28892907
#[stable(feature = "weak_into_raw", since = "1.45.0")]
28902908
pub fn into_raw(self) -> *const T {
@@ -3018,6 +3036,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
30183036
///
30193037
/// assert!(weak_five.upgrade().is_none());
30203038
/// ```
3039+
#[inline]
30213040
#[must_use = "this returns a new `Rc`, \
30223041
without modifying the original weak pointer"]
30233042
#[stable(feature = "rc_weak", since = "1.4.0")]

0 commit comments

Comments
 (0)