1
0
Эх сурвалжийг харах

branch hints (#81)

* branch hints

* add documentation for hint function

Co-authored-by: Fernando Otero <febo@anza.xyz>

* doc for likely

Co-authored-by: Fernando Otero <febo@anza.xyz>

* doc for unlikely

Co-authored-by: Fernando Otero <febo@anza.xyz>

* linter

* rename unlikely_branch to match core

---------

Co-authored-by: Fernando Otero <febo@anza.xyz>
cavemanloverboy 1 сар өмнө
parent
commit
3cfb37d3bf

+ 32 - 0
p-interface/src/lib.rs

@@ -8,3 +8,35 @@ pub mod state;
 pub mod program {
 pub mod program {
     pinocchio_pubkey::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
     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
+    }
+}

+ 2 - 1
p-interface/src/state/account.rs

@@ -1,5 +1,6 @@
 use {
 use {
     super::{account_state::AccountState, COption, Initializable, Transmutable},
     super::{account_state::AccountState, COption, Initializable, Transmutable},
+    crate::likely,
     pinocchio::{program_error::ProgramError, pubkey::Pubkey},
     pinocchio::{program_error::ProgramError, pubkey::Pubkey},
 };
 };
 
 
@@ -158,6 +159,6 @@ unsafe impl Transmutable for Account {
 impl Initializable for Account {
 impl Initializable for Account {
     #[inline(always)]
     #[inline(always)]
     fn is_initialized(&self) -> Result<bool, ProgramError> {
     fn is_initialized(&self) -> Result<bool, ProgramError> {
-        AccountState::try_from(self.state).map(|state| state != AccountState::Uninitialized)
+        AccountState::try_from(self.state).map(|state| likely(state != AccountState::Uninitialized))
     }
     }
 }
 }

+ 6 - 4
p-token/src/processor/mod.rs

@@ -12,6 +12,7 @@ use {
             multisig::{Multisig, MAX_SIGNERS},
             multisig::{Multisig, MAX_SIGNERS},
             Transmutable,
             Transmutable,
         },
         },
+        unlikely,
     },
     },
 };
 };
 
 
@@ -103,9 +104,10 @@ unsafe fn validate_owner(
         return Err(TokenError::OwnerMismatch.into());
         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
         // SAFETY: the caller guarantees that there are no mutable borrows of
         // `owner_account_info` account data and the `load` validates that the
         // `owner_account_info` account data and the `load` validates that the
         // account is initialized; additionally, `Multisig` accounts are only
         // account is initialized; additionally, `Multisig` accounts are only
@@ -130,7 +132,7 @@ unsafe fn validate_owner(
         if num_signers < multisig.m {
         if num_signers < multisig.m {
             return Err(ProgramError::MissingRequiredSignature);
             return Err(ProgramError::MissingRequiredSignature);
         }
         }
-    } else if !owner_account_info.is_signer() {
+    } else if unlikely(!owner_account_info.is_signer()) {
         return Err(ProgramError::MissingRequiredSignature);
         return Err(ProgramError::MissingRequiredSignature);
     }
     }
 
 

+ 2 - 1
p-token/src/processor/shared/transfer.rs

@@ -4,6 +4,7 @@ use {
     pinocchio_token_interface::{
     pinocchio_token_interface::{
         error::TokenError,
         error::TokenError,
         state::{account::Account, load, load_mut, load_mut_unchecked, mint::Mint},
         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
     //   - transfers to different accounts: we need to check that the source and
     //     destination accounts are not frozen, have the same mint, and the source
     //     destination accounts are not frozen, have the same mint, and the source
     //     account has enough tokens.
     //     account has enough tokens.
-    let remaining_amount = if self_transfer {
+    let remaining_amount = if unlikely(self_transfer) {
         if source_account.is_frozen()? {
         if source_account.is_frozen()? {
             return Err(TokenError::AccountFrozen.into());
             return Err(TokenError::AccountFrozen.into());
         }
         }