diff --git a/runtime/src/message_processor.rs b/runtime/src/message_processor.rs index fa7c14669f..2c84292d34 100644 --- a/runtime/src/message_processor.rs +++ b/runtime/src/message_processor.rs @@ -2,10 +2,18 @@ use crate::native_loader; use crate::system_instruction_processor; use solana_sdk::account::{create_keyed_accounts, Account, KeyedAccount}; use solana_sdk::instruction::{CompiledInstruction, InstructionError}; +use solana_sdk::instruction_processor_utils; use solana_sdk::message::Message; use solana_sdk::pubkey::Pubkey; use solana_sdk::system_program; use solana_sdk::transaction::TransactionError; +use std::collections::HashMap; +use std::sync::RwLock; + +#[cfg(unix)] +use libloading::os::unix::*; +#[cfg(windows)] +use libloading::os::windows::*; /// Return true if the slice has any duplicate elements pub fn has_duplicates(xs: &[T]) -> bool { @@ -75,8 +83,11 @@ fn verify_instruction( pub type ProcessInstruction = fn(&Pubkey, &mut [KeyedAccount], &[u8], u64) -> Result<(), InstructionError>; +pub type SymbolCache = RwLock, Symbol>>; + pub struct MessageProcessor { instruction_processors: Vec<(Pubkey, ProcessInstruction)>, + symbol_cache: SymbolCache, } impl Default for MessageProcessor { @@ -88,6 +99,7 @@ impl Default for MessageProcessor { Self { instruction_processors, + symbol_cache: RwLock::new(HashMap::new()), } } } @@ -145,6 +157,7 @@ impl MessageProcessor { &mut keyed_accounts, &instruction.data, tick_height, + &self.symbol_cache, ) } diff --git a/runtime/src/native_loader.rs b/runtime/src/native_loader.rs index a863967b2b..9ebdb1de6e 100644 --- a/runtime/src/native_loader.rs +++ b/runtime/src/native_loader.rs @@ -1,4 +1,5 @@ //! Native loader +use crate::message_processor::SymbolCache; use bincode::deserialize; #[cfg(unix)] use libloading::os::unix::*; @@ -52,12 +53,18 @@ pub fn entrypoint( keyed_accounts: &mut [KeyedAccount], ix_data: &[u8], tick_height: u64, + symbol_cache: &SymbolCache, ) -> Result<(), InstructionError> { if keyed_accounts[0].account.executable { // dispatch it let (names, params) = keyed_accounts.split_at_mut(1); - let name = &names[0].account.data; - let name = match str::from_utf8(name) { + let name_vec = &names[0].account.data; + if let Some(entrypoint) = symbol_cache.read().unwrap().get(name_vec) { + unsafe { + return entrypoint(program_id, params, ix_data, tick_height); + } + } + let name = match str::from_utf8(name_vec) { Ok(v) => v, Err(e) => { warn!("Invalid UTF-8 sequence: {}", e); @@ -81,7 +88,12 @@ pub fn entrypoint( return Err(InstructionError::GenericError); } }; - return entrypoint(program_id, params, ix_data, tick_height); + let ret = entrypoint(program_id, params, ix_data, tick_height); + symbol_cache + .write() + .unwrap() + .insert(name_vec.to_vec(), entrypoint); + return ret; }, Err(e) => { warn!("Unable to load: {:?}", e);