diff --git a/p-interface/src/lib.rs b/p-interface/src/lib.rs index f07b0df5..ab8c3ecb 100644 --- a/p-interface/src/lib.rs +++ b/p-interface/src/lib.rs @@ -8,3 +8,35 @@ pub mod state; pub mod program { pinocchio_pubkey::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); } + +/// A "dummy" function with a hint to the compiler that it is unlikely to be +/// called. +/// +/// This function is used as a hint to the compiler to optimize other code paths +/// instead of the one where the function is used. +#[cold] +pub const fn cold_path() {} + +/// Return the given `bool` value with a hint to the compiler that `true` is the +/// likely case. +#[inline(always)] +pub const fn likely(b: bool) -> bool { + if b { + true + } else { + cold_path(); + false + } +} + +/// Return a given `bool` value with a hint to the compiler that `false` is the +/// likely case. +#[inline(always)] +pub const fn unlikely(b: bool) -> bool { + if b { + cold_path(); + true + } else { + false + } +} diff --git a/p-interface/src/state/account.rs b/p-interface/src/state/account.rs index aa6ba84d..a9ade92a 100644 --- a/p-interface/src/state/account.rs +++ b/p-interface/src/state/account.rs @@ -1,5 +1,6 @@ use { super::{account_state::AccountState, COption, Initializable, Transmutable}, + crate::likely, pinocchio::{program_error::ProgramError, pubkey::Pubkey}, }; @@ -158,6 +159,6 @@ unsafe impl Transmutable for Account { impl Initializable for Account { #[inline(always)] fn is_initialized(&self) -> Result { - AccountState::try_from(self.state).map(|state| state != AccountState::Uninitialized) + AccountState::try_from(self.state).map(|state| likely(state != AccountState::Uninitialized)) } } diff --git a/p-token/src/processor/mod.rs b/p-token/src/processor/mod.rs index 3e626264..155e329f 100644 --- a/p-token/src/processor/mod.rs +++ b/p-token/src/processor/mod.rs @@ -12,6 +12,7 @@ use { multisig::{Multisig, MAX_SIGNERS}, Transmutable, }, + unlikely, }, }; @@ -103,9 +104,10 @@ unsafe fn validate_owner( return Err(TokenError::OwnerMismatch.into()); } - if owner_account_info.data_len() == Multisig::LEN - && owner_account_info.is_owned_by(&TOKEN_PROGRAM_ID) - { + if unlikely( + owner_account_info.data_len() == Multisig::LEN + && owner_account_info.is_owned_by(&TOKEN_PROGRAM_ID), + ) { // SAFETY: the caller guarantees that there are no mutable borrows of // `owner_account_info` account data and the `load` validates that the // account is initialized; additionally, `Multisig` accounts are only @@ -130,7 +132,7 @@ unsafe fn validate_owner( if num_signers < multisig.m { return Err(ProgramError::MissingRequiredSignature); } - } else if !owner_account_info.is_signer() { + } else if unlikely(!owner_account_info.is_signer()) { return Err(ProgramError::MissingRequiredSignature); } diff --git a/p-token/src/processor/shared/transfer.rs b/p-token/src/processor/shared/transfer.rs index db96776a..05061228 100644 --- a/p-token/src/processor/shared/transfer.rs +++ b/p-token/src/processor/shared/transfer.rs @@ -4,6 +4,7 @@ use { pinocchio_token_interface::{ error::TokenError, state::{account::Account, load, load_mut, load_mut_unchecked, mint::Mint}, + unlikely, }, }; @@ -76,7 +77,7 @@ pub fn process_transfer( // - transfers to different accounts: we need to check that the source and // destination accounts are not frozen, have the same mint, and the source // account has enough tokens. - let remaining_amount = if self_transfer { + let remaining_amount = if unlikely(self_transfer) { if source_account.is_frozen()? { return Err(TokenError::AccountFrozen.into()); }