Skip to content

Commit

Permalink
WIP Add an eager per-host ModuleCache
Browse files Browse the repository at this point in the history
  • Loading branch information
graydon committed Mar 7, 2024
1 parent ecb144c commit a702bd5
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 486 deletions.
4 changes: 2 additions & 2 deletions soroban-env-host/benches/common/cost_types/wasm_insn_exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub fn wasm_module_with_n_globals(n: usize) -> Vec<u8> {
pub fn wasm_module_with_n_imports(n: usize) -> Vec<u8> {
let mut me = ModEmitter::default();
let names = Vm::get_all_host_functions();
for (module,name,arity) in names.iter().take(n) {
for (module, name, arity) in names.iter().take(n) {
if *module == "t" {
continue;
}
Expand Down Expand Up @@ -157,7 +157,7 @@ pub fn wasm_module_with_n_types(mut n: usize) -> Vec<u8> {
}

pub fn wasm_module_with_n_elem_segments(n: usize) -> Vec<u8> {
let me = ModEmitter::from_configs(1,n as u32);
let me = ModEmitter::from_configs(1, n as u32);
let mut fe = me.func(Arity(0), 0);
fe.push(Symbol::try_from_small_str("pass").unwrap());
let (mut me, f) = fe.finish();
Expand Down
9 changes: 6 additions & 3 deletions soroban-env-host/src/budget/wasmi_helper.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::{
budget::AsBudget, host::error::TryBorrowOrErr, xdr::ContractCostType, Host, HostError,
budget::{AsBudget, Budget},
host::error::TryBorrowOrErr,
xdr::ContractCostType,
Host, HostError,
};
use wasmi::{errors, FuelConsumptionMode, FuelCosts, ResourceLimiter};

Expand Down Expand Up @@ -110,9 +113,9 @@ pub(crate) fn load_calibrated_fuel_costs() -> FuelCosts {
fuel_costs
}

pub(crate) fn get_wasmi_config(host: &Host) -> Result<wasmi::Config, HostError> {
pub(crate) fn get_wasmi_config(budget: &Budget) -> Result<wasmi::Config, HostError> {
let mut config = wasmi::Config::default();
let fuel_costs = host.as_budget().0.try_borrow_or_err()?.fuel_costs;
let fuel_costs = budget.0.try_borrow_or_err()?.fuel_costs;

// Turn off most optional wasm features, leaving on some post-MVP features
// commonly enabled by Rust and Clang. Make sure all unused features are
Expand Down
17 changes: 16 additions & 1 deletion soroban-env-host/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
impl_wrapping_obj_to_num,
num::*,
storage::Storage,
vm::ModuleCache,
xdr::{
int128_helpers, AccountId, Asset, ContractCostType, ContractEventType, ContractExecutable,
ContractIdPreimage, ContractIdPreimageFromAddress, CreateContractArgs, Duration, Hash,
Expand Down Expand Up @@ -91,6 +92,7 @@ pub struct CoverageScoreboard {

#[derive(Clone, Default)]
struct HostImpl {
module_cache: RefCell<Option<ModuleCache>>,
source_account: RefCell<Option<AccountId>>,
ledger: RefCell<Option<LedgerInfo>>,
objects: RefCell<Vec<HostObject>>,
Expand Down Expand Up @@ -198,7 +200,12 @@ macro_rules! impl_checked_borrow_helpers {
}
};
}

impl_checked_borrow_helpers!(
module_cache,
Option<ModuleCache>,
try_borrow_module_cache,
try_borrow_module_cache_mut
);
impl_checked_borrow_helpers!(
source_account,
Option<AccountId>,
Expand Down Expand Up @@ -327,6 +334,7 @@ impl Host {
#[cfg(all(not(target_family = "wasm"), feature = "tracy"))]
let _client = tracy_client::Client::start();
Self(Rc::new(HostImpl {
module_cache: RefCell::new(None),
source_account: RefCell::new(None),
ledger: RefCell::new(None),
objects: Default::default(),
Expand Down Expand Up @@ -357,6 +365,13 @@ impl Host {
}))
}

pub fn maybe_add_module_cache(&self) -> Result<(), HostError> {
if self.get_ledger_protocol_version()? > ModuleCache::MIN_LEDGER_VERSION {
*self.try_borrow_module_cache_mut()? = Some(ModuleCache::new(self)?);
}
Ok(())
}

pub fn set_source_account(&self, source_account: AccountId) -> Result<(), HostError> {
*self.try_borrow_source_account_mut()? = Some(source_account);
Ok(())
Expand Down
52 changes: 25 additions & 27 deletions soroban-env-host/src/host/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ use crate::{
metered_write_xdr, ContractReentryMode, CreateContractArgs,
},
xdr::{
Asset, ContractCodeCostInputs, ContractCodeEntry, ContractCodeEntryExt,
ContractCodeEntryV1, ContractDataDurability, ContractExecutable, ContractIdPreimage,
Asset, ContractCodeEntry, ContractCodeEntryExt, ContractCodeEntryV1,
ContractDataDurability, ContractExecutable, ContractIdPreimage,
ContractIdPreimageFromAddress, ExtensionPoint, Hash, LedgerKey, LedgerKeyContractCode,
ScAddress, ScErrorCode, ScErrorType,
},
AddressObject, BytesObject, Host, HostError, Symbol, TryFromVal, Vm,
AddressObject, BytesObject, Host, HostError, Symbol, TryFromVal,
};
use std::rc::Rc;

Expand Down Expand Up @@ -165,7 +165,7 @@ impl Host {
)
})?;

let cost_inputs: ContractCodeCostInputs;
let mut ext: ContractCodeEntryExt = ContractCodeEntryExt::V0;

// Instantiate a temporary / throwaway VM using this wasm. This will do
// both quick checks like "does this wasm have the right protocol number
Expand All @@ -179,26 +179,27 @@ impl Host {
// Allow a zero-byte contract when testing, as this is used to make
// native test contracts behave like wasm. They will never be
// instantiated, this is just to exercise their storage logic.
cost_inputs = ContractCodeCostInputs {
n_instructions: 0,
n_functions: 0,
n_globals: 0,
n_table_entries: 0,
n_types: 0,
n_data_segments: 0,
n_elem_segments: 0,
n_imports: 0,
n_exports: 0,
n_memory_pages: 0,
};
} else {
let check_vm = Vm::new(
self,
Hash(hash_bytes.metered_clone(self)?),
wasm_bytes_m.as_slice(),
None,
)?;
cost_inputs = check_vm.get_contract_code_cost_inputs();
let config = crate::budget::get_wasmi_config(self.as_budget())?;
let engine = wasmi::Engine::new(&config);
let module =
crate::vm::ParsedModule::new(self, &engine, wasm_bytes_m.as_slice(), None)?;
// We introduce refined instantiation cost models at the same protocol as we introduce module caching.
if self.get_ledger_protocol_version()? >= super::ModuleCache::MIN_LEDGER_VERSION {
if let Some(cost_inputs) = module.cost_inputs.clone() {
ext = ContractCodeEntryExt::V1(ContractCodeEntryV1 {
ext: ExtensionPoint::V0,
cost_inputs,
});
} else {
return Err(self.err(
ScErrorType::Value,
ScErrorCode::InternalError,
"module cost inputs were not calculated",
&[],
));
}
}
}

let hash_obj = self.add_host_object(self.scbytes_from_slice(hash_bytes.as_slice())?)?;
Expand All @@ -216,10 +217,7 @@ impl Host {
self.with_mut_storage(|storage| {
let data = ContractCodeEntry {
hash: Hash(hash_bytes),
ext: ContractCodeEntryExt::V1(ContractCodeEntryV1 {
ext: ExtensionPoint::V0,
cost_inputs,
}),
ext,
code: wasm_bytes_m,
};
storage.put(
Expand Down
Loading

0 comments on commit a702bd5

Please sign in to comment.