Skip to content
Merged
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
Mark error constructors cold
All `#[cold]` to all error constructors.

As discussed in the [issue #165](#165),
marking functions cold helps LLVM optimize code paths not leading to error.

Although in our case marking only `from` was enough, I took the
liberty of marking all error constructors `#[cold]`.

Note, I marked cold both inner function and public functions, because
LLVM does not always takes into account `#[cold]` attribute of inlined functions,
see [an example in compiled explorer](https://rust.godbolt.org/z/vzxazMMnb).
  • Loading branch information
stepancheg committed Sep 12, 2021
commit fa9bcc0457a2e51593b874cc2f8bcb5608ad43fe
1 change: 1 addition & 0 deletions src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub(crate) enum ChainState<'a> {
}

impl<'a> Chain<'a> {
#[cold]
pub fn new(head: &'a (dyn StdError + 'static)) -> Self {
Chain {
state: ChainState::Linked { next: Some(head) },
Expand Down
13 changes: 13 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ impl Error {
/// created here to ensure that a backtrace exists.
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
#[cold]
pub fn new<E>(error: E) -> Self
where
E: StdError + Send + Sync + 'static,
Expand Down Expand Up @@ -70,6 +71,7 @@ impl Error {
/// .await
/// }
/// ```
#[cold]
pub fn msg<M>(message: M) -> Self
where
M: Display + Debug + Send + Sync + 'static,
Expand All @@ -78,6 +80,7 @@ impl Error {
}

#[cfg(feature = "std")]
#[cold]
pub(crate) fn from_std<E>(error: E, backtrace: Option<Backtrace>) -> Self
where
E: StdError + Send + Sync + 'static,
Expand All @@ -100,6 +103,7 @@ impl Error {
unsafe { Error::construct(error, vtable, backtrace) }
}

#[cold]
pub(crate) fn from_adhoc<M>(message: M, backtrace: Option<Backtrace>) -> Self
where
M: Display + Debug + Send + Sync + 'static,
Expand All @@ -125,6 +129,7 @@ impl Error {
unsafe { Error::construct(error, vtable, backtrace) }
}

#[cold]
pub(crate) fn from_display<M>(message: M, backtrace: Option<Backtrace>) -> Self
where
M: Display + Send + Sync + 'static,
Expand All @@ -151,6 +156,7 @@ impl Error {
}

#[cfg(feature = "std")]
#[cold]
pub(crate) fn from_context<C, E>(context: C, error: E, backtrace: Option<Backtrace>) -> Self
where
C: Display + Send + Sync + 'static,
Expand All @@ -177,6 +183,7 @@ impl Error {
}

#[cfg(feature = "std")]
#[cold]
pub(crate) fn from_boxed(
error: Box<dyn StdError + Send + Sync>,
backtrace: Option<Backtrace>,
Expand Down Expand Up @@ -207,6 +214,7 @@ impl Error {
//
// Unsafe because the given vtable must have sensible behavior on the error
// value of type E.
#[cold]
unsafe fn construct<E>(
error: E,
vtable: &'static ErrorVTable,
Expand Down Expand Up @@ -284,6 +292,7 @@ impl Error {
/// })
/// }
/// ```
#[cold]
pub fn context<C>(self, context: C) -> Self
where
C: Display + Send + Sync + 'static,
Expand Down Expand Up @@ -373,6 +382,7 @@ impl Error {
/// ```
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
#[cold]
pub fn chain(&self) -> Chain {
unsafe { ErrorImpl::chain(self.inner.by_ref()) }
}
Expand Down Expand Up @@ -515,6 +525,7 @@ impl<E> From<E> for Error
where
E: StdError + Send + Sync + 'static,
{
#[cold]
fn from(error: E) -> Self {
let backtrace = backtrace_if_absent!(error);
Error::from_std(error, backtrace)
Expand Down Expand Up @@ -879,6 +890,7 @@ impl ErrorImpl {
.expect("backtrace capture failed")
}

#[cold]
pub(crate) unsafe fn chain(this: Ref<Self>) -> Chain {
Chain::new(Self::error(this))
}
Expand Down Expand Up @@ -917,6 +929,7 @@ where
}

impl From<Error> for Box<dyn StdError + Send + Sync + 'static> {
#[cold]
fn from(error: Error) -> Self {
let outer = ManuallyDrop::new(error);
unsafe {
Expand Down
3 changes: 3 additions & 0 deletions src/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ pub trait AdhocKind: Sized {
impl<T> AdhocKind for &T where T: ?Sized + Display + Debug + Send + Sync + 'static {}

impl Adhoc {
#[cold]
pub fn new<M>(self, message: M) -> Error
where
M: Display + Debug + Send + Sync + 'static,
Expand All @@ -82,6 +83,7 @@ pub trait TraitKind: Sized {
impl<E> TraitKind for E where E: Into<Error> {}

impl Trait {
#[cold]
pub fn new<E>(self, error: E) -> Error
where
E: Into<Error>,
Expand All @@ -106,6 +108,7 @@ impl BoxedKind for Box<dyn StdError + Send + Sync> {}

#[cfg(feature = "std")]
impl Boxed {
#[cold]
pub fn new(self, error: Box<dyn StdError + Send + Sync>) -> Error {
let backtrace = backtrace_if_absent!(error);
Error::from_boxed(error, backtrace)
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,7 @@ pub mod private {
pub use crate::kind::BoxedKind;
}

#[cold]
pub fn new_adhoc<M>(message: M) -> Error
where
M: Display + Debug + Send + Sync + 'static,
Expand Down