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 Dec 3, 2023
2 parents 62252d1 + 1ce2370 commit 979a9ce
Show file tree
Hide file tree
Showing 48 changed files with 1,036 additions and 570 deletions.
78 changes: 63 additions & 15 deletions crates/wasmi/benches/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ criterion_group! {
bench_execute_recursive_trap,
bench_execute_host_calls,
bench_execute_fuse,
bench_execute_divrem,
bench_execute_fibonacci,
bench_execute_recursive_is_even,
bench_execute_memory_sum,
Expand All @@ -97,56 +98,85 @@ enum FuelMetering {
Disabled,
}

fn bench_translate_for(c: &mut Criterion, name: &str, path: &str, fuel_metering: FuelMetering) {
/// How to translate a Wasm module.
enum Validation {
/// Uses [`Module::new`].
Checked,
/// Uses [`Module::new_unchecked`].
Unchecked,
}

fn bench_translate_for(
c: &mut Criterion,
name: &str,
path: &str,
validation: Validation,
fuel_metering: FuelMetering,
) {
let fuel_id = match fuel_metering {
FuelMetering::Enabled => "fuel",
FuelMetering::Disabled => "default",
};
let bench_id = format!("translate/{name}/{fuel_id}");
let safety = match validation {
Validation::Checked => "checked",
Validation::Unchecked => "unchecked",
};
let bench_id = format!("translate/{name}/{safety}/{fuel_id}");
let mut config = bench_config();
if matches!(fuel_metering, FuelMetering::Enabled) {
config.consume_fuel(true);
}
let create_module = match validation {
Validation::Checked => {
|engine: &Engine, bytes: &[u8]| -> Module { Module::new(&engine, &bytes[..]).unwrap() }
}
Validation::Unchecked => |engine: &Engine, bytes: &[u8]| -> Module {
// Safety: We made sure that all translation benchmark inputs are valid Wasm.
unsafe { Module::new_unchecked(engine, &bytes[..]).unwrap() }
},
};
c.bench_function(&bench_id, |b| {
let wasm_bytes = load_wasm_from_file(path);
b.iter(|| {
let engine = Engine::new(&config);
let _module = Module::new(&engine, &wasm_bytes[..]).unwrap();
_ = create_module(&engine, &wasm_bytes[..]);
})
});
}

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_for_all(c: &mut Criterion, name: &str, path: &str) {
bench_translate_for(c, name, path, Validation::Checked, FuelMetering::Disabled);
bench_translate_for(c, name, path, Validation::Checked, FuelMetering::Enabled);
bench_translate_for(c, name, path, Validation::Unchecked, FuelMetering::Disabled);
bench_translate_for(c, name, path, Validation::Unchecked, FuelMetering::Enabled);
}

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

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

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

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

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

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

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

fn bench_instantiate_wasm_kernel(c: &mut Criterion) {
Expand Down Expand Up @@ -851,20 +881,38 @@ fn bench_execute_fuse(c: &mut Criterion) {
let (mut store, instance) = load_instance_from_wat(include_bytes!("wat/fuse.wat"));
let mut bench_fuse = |bench_id: &str, func_name: &str, input: i32| {
c.bench_function(bench_id, |b| {
let fib = instance
let test = instance
.get_export(&store, func_name)
.and_then(Extern::into_func)
.unwrap()
.typed::<i32, i32>(&store)
.unwrap();
b.iter(|| {
assert_eq!(fib.call(&mut store, input).unwrap(), input);
assert_eq!(test.call(&mut store, input).unwrap(), input);
});
});
};
bench_fuse("execute/fuse", "test", 1_000_000);
}

fn bench_execute_divrem(c: &mut Criterion) {
let (mut store, instance) = load_instance_from_wat(include_bytes!("wat/divrem.wat"));
let mut bench_fuse = |bench_id: &str, func_name: &str, input: i32| {
c.bench_function(bench_id, |b| {
let fib = instance
.get_export(&store, func_name)
.and_then(Extern::into_func)
.unwrap()
.typed::<i32, i32>(&store)
.unwrap();
b.iter(|| {
assert_eq!(fib.call(&mut store, input).unwrap(), 0);
});
});
};
bench_fuse("execute/divrem", "test", 250_000);
}

fn bench_execute_fibonacci(c: &mut Criterion) {
const fn fib(n: i64) -> i64 {
if n <= 1 {
Expand Down
30 changes: 30 additions & 0 deletions crates/wasmi/benches/wat/divrem.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
(module
(func (export "test") (param $n i32) (result i32)
(local $m i64)
(local $tmp32 i32)
(local $tmp64 i64)
(loop $continue
;; n -= 1
(local.set $n
(i32.sub
(local.get $n)
(i32.const 1)
)
)
;; m = n
(local.set $m (i64.extend_i32_u (local.get $n)))
;; execute a bunch of div and rem instructions with immediate `rhs` values
(local.set $tmp32 (i32.div_s (local.get $n) (i32.const 3)))
(local.set $tmp32 (i32.div_u (local.get $n) (i32.const 3)))
(local.set $tmp32 (i32.rem_s (local.get $n) (i32.const 3)))
(local.set $tmp32 (i32.rem_u (local.get $n) (i32.const 3)))
(local.set $tmp64 (i64.div_s (local.get $m) (i64.const 3)))
(local.set $tmp64 (i64.div_u (local.get $m) (i64.const 3)))
(local.set $tmp64 (i64.rem_s (local.get $m) (i64.const 3)))
(local.set $tmp64 (i64.rem_u (local.get $m) (i64.const 3)))
;; continue if $n != 0
(br_if $continue (local.get $n))
)
(return (local.get $n))
)
)
33 changes: 25 additions & 8 deletions crates/wasmi/src/engine/bytecode/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use super::{
TableIdx,
UnaryInstr,
};
use core::num::{NonZeroI32, NonZeroI64, NonZeroU32, NonZeroU64};

macro_rules! constructor_for {
(
Expand Down Expand Up @@ -264,6 +265,30 @@ constructor_for_branch_binop_imm! {
fn branch_i64_ge_u_imm(u64) -> Self::BranchI64GeUImm;
}

macro_rules! constructor_for_branch_binop_imm {
( $( fn $name:ident($ty:ty) -> Self::$op_code:ident; )* ) => {
impl Instruction {
$(
#[doc = concat!("Creates a new [`Instruction::", stringify!($op_code), "`].")]
pub fn $name(result: Register, lhs: Register, rhs: impl Into<Const16<$ty>>) -> Self {
Self::$op_code(BinInstrImm16::new(result, lhs, rhs.into()))
}
)*
}
}
}
constructor_for_branch_binop_imm! {
fn i32_div_s_imm16(NonZeroI32) -> Self::I32DivSImm16;
fn i32_div_u_imm16(NonZeroU32) -> Self::I32DivUImm16;
fn i32_rem_s_imm16(NonZeroI32) -> Self::I32RemSImm16;
fn i32_rem_u_imm16(NonZeroU32) -> Self::I32RemUImm16;

fn i64_div_s_imm16(NonZeroI64) -> Self::I64DivSImm16;
fn i64_div_u_imm16(NonZeroU64) -> Self::I64DivUImm16;
fn i64_rem_s_imm16(NonZeroI64) -> Self::I64RemSImm16;
fn i64_rem_u_imm16(NonZeroU64) -> Self::I64RemUImm16;
}

impl Instruction {
/// Creates a new [`Instruction::Const32`] from the given `value`.
pub fn const32(value: impl Into<AnyConst32>) -> Self {
Expand Down Expand Up @@ -1541,35 +1566,27 @@ impl Instruction {
// Integer Division & Remainder

fn i32_div_u(binary) -> Self::I32DivU;
fn i32_div_u_imm16(binary_u32imm16) -> Self::I32DivUImm16;
fn i32_div_u_imm16_rev(binary_u32imm16_rev) -> Self::I32DivUImm16Rev;

fn i64_div_u(binary) -> Self::I64DivU;
fn i64_div_u_imm16(binary_u64imm16) -> Self::I64DivUImm16;
fn i64_div_u_imm16_rev(binary_u64imm16_rev) -> Self::I64DivUImm16Rev;

fn i32_div_s(binary) -> Self::I32DivS;
fn i32_div_s_imm16(binary_i32imm16) -> Self::I32DivSImm16;
fn i32_div_s_imm16_rev(binary_i32imm16_rev) -> Self::I32DivSImm16Rev;

fn i64_div_s(binary) -> Self::I64DivS;
fn i64_div_s_imm16(binary_i64imm16) -> Self::I64DivSImm16;
fn i64_div_s_imm16_rev(binary_i64imm16_rev) -> Self::I64DivSImm16Rev;

fn i32_rem_u(binary) -> Self::I32RemU;
fn i32_rem_u_imm16(binary_u32imm16) -> Self::I32RemUImm16;
fn i32_rem_u_imm16_rev(binary_u32imm16_rev) -> Self::I32RemUImm16Rev;

fn i64_rem_u(binary) -> Self::I64RemU;
fn i64_rem_u_imm16(binary_u64imm16) -> Self::I64RemUImm16;
fn i64_rem_u_imm16_rev(binary_u64imm16_rev) -> Self::I64RemUImm16Rev;

fn i32_rem_s(binary) -> Self::I32RemS;
fn i32_rem_s_imm16(binary_i32imm16) -> Self::I32RemSImm16;
fn i32_rem_s_imm16_rev(binary_i32imm16_rev) -> Self::I32RemSImm16Rev;

fn i64_rem_s(binary) -> Self::I64RemS;
fn i64_rem_s_imm16(binary_i64imm16) -> Self::I64RemSImm16;
fn i64_rem_s_imm16_rev(binary_i64imm16_rev) -> Self::I64RemSImm16Rev;

// Integer Bitwise Logic
Expand Down
Loading

0 comments on commit 979a9ce

Please sign in to comment.