Skip to content

Commit

Permalink
Merge branch 'master' into remove-duplicated-checks
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbepop authored Nov 28, 2023
2 parents c250267 + 52f180c commit f3b7c3b
Show file tree
Hide file tree
Showing 8 changed files with 608 additions and 476 deletions.
38 changes: 28 additions & 10 deletions crates/wasmi/benches/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,43 +92,61 @@ const WASM_KERNEL: &str =
const REVCOMP_INPUT: &[u8] = include_bytes!("wasm/wasm_kernel/res/revcomp-input.txt");
const REVCOMP_OUTPUT: &[u8] = include_bytes!("wasm/wasm_kernel/res/revcomp-output.txt");

fn bench_translate_for(c: &mut Criterion, name: &str, path: &str) {
let bench_id = format!("translate/{name}");
enum FuelMetering {
Enabled,
Disabled,
}

fn bench_translate_for(c: &mut Criterion, name: &str, path: &str, fuel_metering: FuelMetering) {
let fuel_id = match fuel_metering {
FuelMetering::Enabled => "fuel",
FuelMetering::Disabled => "default",
};
let bench_id = format!("translate/{name}/{fuel_id}");
let mut config = bench_config();
if matches!(fuel_metering, FuelMetering::Enabled) {
config.consume_fuel(true);
}
c.bench_function(&bench_id, |b| {
let wasm_bytes = load_wasm_from_file(path);
b.iter(|| {
let engine = Engine::new(&bench_config());
let engine = Engine::new(&config);
let _module = Module::new(&engine, &wasm_bytes[..]).unwrap();
})
});
}

fn bench_translate_for_both(c: &mut Criterion, name: &str, path: &str) {
bench_translate_for(c, name, path, FuelMetering::Disabled);
bench_translate_for(c, name, path, FuelMetering::Enabled);
}

fn bench_translate_wasm_kernel(c: &mut Criterion) {
bench_translate_for(c, "wasm_kernel", WASM_KERNEL)
bench_translate_for_both(c, "wasm_kernel", WASM_KERNEL);
}

fn bench_translate_spidermonkey(c: &mut Criterion) {
bench_translate_for(c, "spidermonkey", "benches/wasm/spidermonkey.wasm")
bench_translate_for_both(c, "spidermonkey", "benches/wasm/spidermonkey.wasm");
}

fn bench_translate_bz2(c: &mut Criterion) {
bench_translate_for(c, "bz2", "benches/wasm/bz2.wasm")
bench_translate_for_both(c, "bz2", "benches/wasm/bz2.wasm");
}

fn bench_translate_pulldown_cmark(c: &mut Criterion) {
bench_translate_for(c, "pulldown_cmark", "benches/wasm/pulldown-cmark.wasm")
bench_translate_for_both(c, "pulldown_cmark", "benches/wasm/pulldown-cmark.wasm");
}

fn bench_translate_erc20(c: &mut Criterion) {
bench_translate_for(c, "erc20", "benches/wasm/erc20.wasm")
bench_translate_for_both(c, "erc20", "benches/wasm/erc20.wasm");
}

fn bench_translate_erc721(c: &mut Criterion) {
bench_translate_for(c, "erc721", "benches/wasm/erc721.wasm")
bench_translate_for_both(c, "erc721", "benches/wasm/erc721.wasm");
}

fn bench_translate_erc1155(c: &mut Criterion) {
bench_translate_for(c, "erc1155", "benches/wasm/erc1155.wasm")
bench_translate_for_both(c, "erc1155", "benches/wasm/erc1155.wasm");
}

fn bench_instantiate_wasm_kernel(c: &mut Criterion) {
Expand Down
141 changes: 83 additions & 58 deletions crates/wasmi/src/engine/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,63 +105,97 @@ pub enum FuelConsumptionMode {
#[derive(Debug, Copy, Clone)]
pub struct FuelCosts {
/// The base fuel costs for all instructions.
pub base: u64,
/// The fuel cost for instruction operating on Wasm entities.
///
/// # Note
///
/// A Wasm entity is one of `func`, `global`, `memory` or `table`.
/// Those instructions are usually a bit more costly since they need
/// multiple indirect accesses through the Wasm instance and store.
pub entity: u64,
/// The fuel cost offset for `memory.load` instructions.
pub load: u64,
/// The fuel cost offset for `memory.store` instructions.
pub store: u64,
/// The fuel cost offset for `call` and `call_indirect` instructions.
pub call: u64,
/// Determines how many moved stack values consume one fuel upon a branch or return instruction.
///
/// # Note
///
/// If this is zero then processing [`DropKeep`] costs nothing.
branch_kept_per_fuel: u64,
/// Determines how many function locals consume one fuel per function call.
base: u64,
/// The register copies that can be performed per unit of fuel.
copies_per_fuel: NonZeroU64,
/// The bytes that can be copied per unit of fuel.
bytes_per_fuel: NonZeroU64,
}

impl FuelCosts {
/// Returns the base fuel costs for all `wasmi` IR instructions.
pub fn base(&self) -> u64 {
self.base
}

/// Returns the base fuel costs for all `wasmi` IR entity related instructions.
pub fn entity(&self) -> u64 {
// Note: For simplicity we currently simply use base costs.
self.base
}

/// Returns the base fuel costs for all `wasmi` IR load instructions.
pub fn load(&self) -> u64 {
// Note: For simplicity we currently simply use base costs.
self.base
}

/// Returns the base fuel costs for all `wasmi` IR store instructions.
pub fn store(&self) -> u64 {
// Note: For simplicity we currently simply use base costs.
self.base
}

/// Returns the base fuel costs for all `wasmi` IR call instructions.
pub fn call(&self) -> u64 {
// Note: For simplicity we currently simply use base costs.
self.base
}

/// Returns the number of register copies performed per unit of fuel.
fn copies_per_fuel(&self) -> NonZeroU64 {
self.copies_per_fuel
}

/// Returns the number of byte copies performed per unit of fuel.
fn bytes_per_fuel(&self) -> NonZeroU64 {
self.bytes_per_fuel
}

/// Returns the fuel costs for `len_copies` register copies in `wasmi` IR.
///
/// # Note
///
/// - This is also applied to all function parameters since
/// they are translated to local variable slots.
/// - If this is zero then processing function locals costs nothing.
func_locals_per_fuel: u64,
/// How many memory bytes can be processed per fuel in a `bulk-memory` instruction.
/// Registers are copied for the following `wasmi` IR instructions:
///
/// - calls (parameter passing)
/// - `copy_span`
/// - `copy_many`
/// - `return_span`
/// - `return_many`
/// - `table.grow` (+ variants)
/// - `table.copy` (+ variants)
/// - `table.fill` (+ variants)
/// - `table.init` (+ variants)
pub fn fuel_for_copies(&self, len_copies: u64) -> u64 {
Self::costs_per(len_copies, self.copies_per_fuel())
}

/// Returns the fuel costs for `len_copies` register copies in `wasmi` IR.
///
/// # Note
///
/// If this is zero then processing memory bytes costs nothing.
memory_bytes_per_fuel: u64,
/// How many table elements can be processed per fuel in a `bulk-table` instruction.
///
/// # Note
/// Registers are copied for the following `wasmi` IR instructions:
///
/// If this is zero then processing table elements costs nothing.
table_elements_per_fuel: u64,
}
/// - `memory.grow`
/// - `memory.copy`
/// - `memory.fill`
/// - `memory.init`
pub fn fuel_for_bytes(&self, len_bytes: u64) -> u64 {
Self::costs_per(len_bytes, self.bytes_per_fuel())
}

impl FuelCosts {
/// Returns the fuel consumption of the amount of items with costs per items.
fn costs_per(len_items: u64, items_per_fuel: u64) -> u64 {
NonZeroU64::new(items_per_fuel)
.map(|items_per_fuel| len_items / items_per_fuel)
.unwrap_or(0)
fn costs_per(len_items: u64, items_per_fuel: NonZeroU64) -> u64 {
len_items / items_per_fuel
}

/// Returns the fuel consumption for branches and returns using the given [`DropKeep`].
pub fn fuel_for_drop_keep(&self, drop_keep: DropKeep) -> u64 {
if drop_keep.drop() == 0 {
return 0;
}
Self::costs_per(u64::from(drop_keep.keep()), self.branch_kept_per_fuel)
Self::costs_per(u64::from(drop_keep.keep()), self.copies_per_fuel())
}

/// Returns the fuel consumption for calling a function with the amount of local variables.
Expand All @@ -170,35 +204,26 @@ impl FuelCosts {
///
/// Function parameters are also treated as local variables.
pub fn fuel_for_locals(&self, locals: u64) -> u64 {
Self::costs_per(locals, self.func_locals_per_fuel)
}

/// Returns the fuel consumption for processing the amount of memory bytes.
pub fn fuel_for_bytes(&self, bytes: u64) -> u64 {
Self::costs_per(bytes, self.memory_bytes_per_fuel)
self.fuel_for_copies(locals)
}

/// Returns the fuel consumption for processing the amount of table elements.
pub fn fuel_for_elements(&self, elements: u64) -> u64 {
Self::costs_per(elements, self.table_elements_per_fuel)
self.fuel_for_copies(elements)
}
}

impl Default for FuelCosts {
fn default() -> Self {
let memory_bytes_per_fuel = 64;
let bytes_per_fuel = 64;
let bytes_per_register = size_of::<UntypedValue>() as u64;
let registers_per_fuel = memory_bytes_per_fuel / bytes_per_register;
let registers_per_fuel = bytes_per_fuel / bytes_per_register;
Self {
base: 1,
entity: 1,
load: 1,
store: 1,
call: 1,
func_locals_per_fuel: registers_per_fuel,
branch_kept_per_fuel: registers_per_fuel,
memory_bytes_per_fuel,
table_elements_per_fuel: registers_per_fuel,
copies_per_fuel: NonZeroU64::new(registers_per_fuel)
.unwrap_or_else(|| panic!("invalid zero value for copies_per_fuel value")),
bytes_per_fuel: NonZeroU64::new(bytes_per_fuel)
.unwrap_or_else(|| panic!("invalid zero value for copies_per_fuel value")),
}
}
}
Expand Down
Loading

0 comments on commit f3b7c3b

Please sign in to comment.