From 360f2f036d14889f4de37a8b4b6aad0d09772aad Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 31 Mar 2018 23:19:02 +0200 Subject: [PATCH 1/3] Inline most of the code paths for conversions with boxed slices This helps with the specific problem described in #49541, obviously without making any large change to how inlining works in the general case. Everything involved in the conversions is made `#[inline]`, except for the `>::into_boxed_slice` entry point which is made `#[inline(always)]` after checking that duplicating the function mentioned in the issue prevented its inlining if I only annotate it with `#[inline]`. For the record, that function was: ```rust pub fn foo() -> Box<[u8]> { vec![0].into_boxed_slice() } ``` To help the inliner's job, we also hoist a `self.capacity() != self.len` check in `>::shrink_to_fit` and mark it as `#[inline]` too. --- src/liballoc/boxed.rs | 2 ++ src/liballoc/str.rs | 3 +++ src/liballoc/string.rs | 1 + src/liballoc/vec.rs | 6 +++++- 4 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index fdc3ef4efb866..2fc60a799f3bb 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -577,6 +577,7 @@ impl<'a, T: Copy> From<&'a [T]> for Box<[T]> { #[stable(feature = "box_from_slice", since = "1.17.0")] impl<'a> From<&'a str> for Box { + #[inline] fn from(s: &'a str) -> Box { unsafe { from_boxed_utf8_unchecked(Box::from(s.as_bytes())) } } @@ -584,6 +585,7 @@ impl<'a> From<&'a str> for Box { #[stable(feature = "boxed_str_conv", since = "1.19.0")] impl From> for Box<[u8]> { + #[inline] fn from(s: Box) -> Self { unsafe { Box::from_raw(Box::into_raw(s) as *mut [u8]) } } diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index d5ef41df0d850..6f05c52eb5799 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -1811,6 +1811,7 @@ impl str { /// assert_eq!(*boxed_bytes, *s.as_bytes()); /// ``` #[stable(feature = "str_box_extras", since = "1.20.0")] + #[inline] pub fn into_boxed_bytes(self: Box) -> Box<[u8]> { self.into() } @@ -2049,6 +2050,7 @@ impl str { /// assert_eq!(boxed_str.into_string(), string); /// ``` #[stable(feature = "box_str", since = "1.4.0")] + #[inline] pub fn into_string(self: Box) -> String { let slice = Box::<[u8]>::from(self); unsafe { String::from_utf8_unchecked(slice.into_vec()) } @@ -2307,6 +2309,7 @@ impl str { /// assert_eq!("☺", &*smile); /// ``` #[stable(feature = "str_box_extras", since = "1.20.0")] +#[inline] pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box { Box::from_raw(Box::into_raw(v) as *mut str) } diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index aa202e2362892..95d5b30b67daa 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -1587,6 +1587,7 @@ impl String { /// let b = s.into_boxed_str(); /// ``` #[stable(feature = "box_str", since = "1.4.0")] + #[inline] pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); unsafe { from_boxed_utf8_unchecked(slice) } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 2eedb964f88ba..e3c036e6aacaf 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -582,8 +582,11 @@ impl Vec { /// assert!(vec.capacity() >= 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline] pub fn shrink_to_fit(&mut self) { - self.buf.shrink_to_fit(self.len); + if self.capacity() != self.len { + self.buf.shrink_to_fit(self.len); + } } /// Shrinks the capacity of the vector with a lower bound. @@ -636,6 +639,7 @@ impl Vec { /// assert_eq!(slice.into_vec().capacity(), 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] pub fn into_boxed_slice(mut self) -> Box<[T]> { unsafe { self.shrink_to_fit(); From d4dff03e7c6decd6b545dcb290d2c592969b3d81 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 8 Apr 2018 09:03:33 +0200 Subject: [PATCH 2/3] Remove inline on Vec::shrink_to_fit as asked by Alex --- src/liballoc/vec.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e3c036e6aacaf..3fff28469fed5 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -582,7 +582,6 @@ impl Vec { /// assert!(vec.capacity() >= 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[inline] pub fn shrink_to_fit(&mut self) { if self.capacity() != self.len { self.buf.shrink_to_fit(self.len); From b59fa0d9e81fe36c5d298f8f828aaf0755e96f89 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 15 Apr 2018 10:34:57 +0200 Subject: [PATCH 3/3] Remove #[inline(always)] on Vec::into_boxed_slice --- src/liballoc/vec.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 3fff28469fed5..a6498b8861e14 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -638,7 +638,6 @@ impl Vec { /// assert_eq!(slice.into_vec().capacity(), 3); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] pub fn into_boxed_slice(mut self) -> Box<[T]> { unsafe { self.shrink_to_fit();