Skip to content

Commit 7fe8ada

Browse files
chore: general cleanup, fix performance regressions
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 676be92 commit 7fe8ada

15 files changed

Lines changed: 168 additions & 142 deletions

File tree

‎crates/tinywasm/benches/argon2id.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ fn criterion_benchmark(c: &mut Criterion) {
3434
let twasm = argon2id_to_twasm(&module).expect("argon2id_to_twasm");
3535
let mut group = c.benchmark_group("argon2id");
3636

37-
group.measurement_time(std::time::Duration::from_secs(2));
38-
group.bench_function("argon2id_parse", |b| b.iter(argon2id_parse));
39-
group.bench_function("argon2id_to_twasm", |b| b.iter(|| argon2id_to_twasm(&module)));
40-
group.bench_function("argon2id_from_twasm", |b| b.iter(|| argon2id_from_twasm(&twasm)));
37+
// group.measurement_time(std::time::Duration::from_secs(2));
38+
// group.bench_function("argon2id_parse", |b| b.iter(argon2id_parse));
39+
// group.bench_function("argon2id_to_twasm", |b| b.iter(|| argon2id_to_twasm(&module)));
40+
// group.bench_function("argon2id_from_twasm", |b| b.iter(|| argon2id_from_twasm(&twasm)));
4141

4242
group.measurement_time(std::time::Duration::from_secs(10));
4343
group.bench_function("argon2id", |b| b.iter(|| argon2id_run(module.clone())));

‎crates/tinywasm/benches/fibonacci.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ fn criterion_benchmark(c: &mut Criterion) {
3939
let twasm = fibonacci_to_twasm(&module).expect("fibonacci_to_twasm");
4040
let mut group = c.benchmark_group("fibonacci");
4141

42-
group.measurement_time(std::time::Duration::from_secs(2));
43-
group.bench_function("fibonacci_parse", |b| b.iter(fibonacci_parse));
44-
group.bench_function("fibonacci_to_twasm", |b| b.iter(|| fibonacci_to_twasm(&module)));
45-
group.bench_function("fibonacci_from_twasm", |b| b.iter(|| fibonacci_from_twasm(&twasm)));
42+
// group.measurement_time(std::time::Duration::from_secs(2));
43+
// group.bench_function("fibonacci_parse", |b| b.iter(fibonacci_parse));
44+
// group.bench_function("fibonacci_to_twasm", |b| b.iter(|| fibonacci_to_twasm(&module)));
45+
// group.bench_function("fibonacci_from_twasm", |b| b.iter(|| fibonacci_from_twasm(&twasm)));
4646

4747
group.measurement_time(std::time::Duration::from_secs(10));
4848
group.bench_function("fibonacci_iterative_60", |b| b.iter(|| fibonacci_run(module.clone(), false, 60)));

‎crates/tinywasm/benches/tinywasm.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ fn tinywasm_from_twasm(twasm: &[u8]) -> Result<Module> {
2323
}
2424

2525
fn tinywasm_run(module: &Module) -> Result<()> {
26-
let engine = Engine::new(Config::default().with_memory_backend(MemoryBackend::paged(64 * 1024)));
26+
let engine = Engine::new(Config::default());
2727
let mut store = Store::new(engine);
2828
let mut imports = Imports::default();
2929
imports.define("env", "printi32", HostFunction::from(&mut store, |_: FuncContext<'_>, _: i32| Ok(())));

‎crates/tinywasm/src/func.rs‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ impl FuncContext<'_> {
278278
self.store
279279
.get_module_instance(self.module_id)
280280
.unwrap_or_else(|| unreachable!("invalid module instance id in host function context: {}", self.module_id))
281+
.clone()
281282
}
282283

283284
/// Get a memory export.
@@ -566,13 +567,11 @@ fn collect_call_results(
566567
func_ty: &FuncType,
567568
) -> Result<Vec<WasmValue>> {
568569
debug_assert!(value_stack.len() >= func_ty.results().len()); // m values are on the top of the stack (Ensured by validation)
569-
let mut res: Vec<_> = func_ty
570-
.results()
571-
.iter()
572-
.rev()
573-
.map(|&ty| state.attach_value(value_stack.pop_tinyvalue(ty), ty).expect("validated function result"))
574-
.collect();
575-
res.reverse(); // reverse to get the original order
570+
let results = func_ty.results();
571+
let mut res = vec![WasmValue::I32(0); results.len()];
572+
for (i, &ty) in results.iter().enumerate().rev() {
573+
res[i] = value_stack.pop_wasmvalue(state, ty);
574+
}
576575
Ok(res)
577576
}
578577

‎crates/tinywasm/src/interpreter/executor.rs‎

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
4646

4747
pub(crate) fn new(store: &'store mut Store, cf: CallFrame, call_stack_base: u32) -> Self {
4848
let wasm_func = store.state.get_wasm_func(cf.func_addr);
49-
let module = store.get_module_instance_internal(wasm_func.owner);
49+
let module = store
50+
.get_module_instance(wasm_func.owner)
51+
.unwrap_or_else(|| unreachable!("invalid module instance"))
52+
.clone();
5053
Self { module, cf, func: wasm_func.func.clone(), store, call_stack_base }
5154
}
5255

@@ -1004,7 +1007,11 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
10041007
self.store.call_stack.push(self.cf)?;
10051008
self.cf = CallFrame::new(func_addr, locals_base, wasm_func.func.locals);
10061009
if wasm_func.owner != self.module.id() {
1007-
self.module = self.store.get_module_instance_internal(wasm_func.owner);
1010+
self.module = self
1011+
.store
1012+
.get_module_instance(wasm_func.owner)
1013+
.unwrap_or_else(|| unreachable!("invalid module instance"))
1014+
.clone();
10081015
}
10091016

10101017
Ok(())
@@ -1023,7 +1030,11 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
10231030
};
10241031
self.cf = CallFrame::new(func_addr, locals_base, wasm_func.func.locals);
10251032
if wasm_func.owner != self.module.id() {
1026-
self.module = self.store.get_module_instance_internal(wasm_func.owner);
1033+
self.module = self
1034+
.store
1035+
.get_module_instance(wasm_func.owner)
1036+
.unwrap_or_else(|| unreachable!("invalid module instance"))
1037+
.clone();
10271038
}
10281039

10291040
Ok(())
@@ -1039,8 +1050,7 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
10391050
let mut params = Vec::new();
10401051
params.try_reserve_exact(param_types.len()).map_err(|_| Trap::OutOfMemory)?;
10411052
for &ty in param_types.iter().rev() {
1042-
let value = self.store.value_stack.pop_tinyvalue(ty);
1043-
params.push(self.store.state.attach_value(value, ty).expect("validated host argument"));
1053+
params.push(self.store.value_stack.pop_wasmvalue(&self.store.state, ty));
10441054
}
10451055
params.reverse();
10461056
if params_may_gc {
@@ -1094,13 +1104,12 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
10941104

10951105
fn exec_call_self(&mut self) -> Result<(), Trap> {
10961106
self.charge_call_fuel(FUEL_COST_CALL_TOTAL);
1097-
1098-
self.store.call_stack.push(self.cf)?;
10991107
let Ok(locals_base) = self.store.value_stack.enter_locals(&self.func.params, &self.func.locals) else {
11001108
cold_path();
11011109
return Err(Trap::CallStackOverflow);
11021110
};
1103-
self.cf = CallFrame::new(self.cf.func_addr, locals_base, self.func.locals);
1111+
let new = CallFrame::new(self.cf.func_addr, locals_base, self.func.locals);
1112+
self.store.call_stack.push(core::mem::replace(&mut self.cf, new))?;
11041113

11051114
Ok(())
11061115
}
@@ -1195,7 +1204,11 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
11951204
let wasm_func = self.store.state.get_wasm_func(caller.func_addr);
11961205
self.func = wasm_func.func.clone();
11971206
if wasm_func.owner != self.module.id() {
1198-
self.module = self.store.get_module_instance_internal(wasm_func.owner);
1207+
self.module = self
1208+
.store
1209+
.get_module_instance(wasm_func.owner)
1210+
.unwrap_or_else(|| unreachable!("invalid module instance"))
1211+
.clone();
11991212
}
12001213
self.cf = caller;
12011214
false

‎crates/tinywasm/src/interpreter/simd/mod.rs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ use core::arch::wasm32 as wasm;
1313
use core::arch::wasm64 as wasm;
1414

1515
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
16+
#[repr(transparent)]
1617
/// A 128-bit SIMD value
17-
pub struct Value128(pub(super) [u8; 16]);
18+
pub struct Value128(pub(crate) [u8; 16]);
1819

1920
impl From<[u8; 16]> for Value128 {
2021
fn from(bytes: [u8; 16]) -> Self {
@@ -24,12 +25,12 @@ impl From<[u8; 16]> for Value128 {
2425

2526
impl Value128 {
2627
#[inline(always)]
27-
pub fn from_le_bytes(bytes: [u8; 16]) -> Self {
28+
pub const fn from_le_bytes(bytes: [u8; 16]) -> Self {
2829
Self(bytes)
2930
}
3031

3132
#[inline(always)]
32-
pub fn to_le_bytes(self) -> [u8; 16] {
33+
pub const fn to_le_bytes(self) -> [u8; 16] {
3334
self.0
3435
}
3536
}

‎crates/tinywasm/src/interpreter/stack/value_stack.rs‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -244,20 +244,21 @@ impl ValueStack {
244244

245245
pub(crate) fn push_dyn(&mut self, value: TinyWasmValue) -> Result<(), Trap> {
246246
match value {
247-
TinyWasmValue::Value32(v) => self.stack_32.push(v)?,
248-
TinyWasmValue::Value64(v) => self.stack_64.push(v)?,
249-
TinyWasmValue::Value128(v) => self.stack_128.push(v)?,
250-
TinyWasmValue::ValueRef(v) => self.stack_32.push(v.raw())?,
247+
TinyWasmValue::Value32(v) => self.stack_32.push(v),
248+
TinyWasmValue::Value64(v) => self.stack_64.push(v),
249+
TinyWasmValue::Value128(v) => self.stack_128.push(v),
250+
TinyWasmValue::ValueRef(v) => self.stack_32.push(v.raw()),
251251
}
252-
Ok(())
253252
}
254253

255-
pub(crate) fn pop_tinyvalue(&mut self, val_type: WasmType) -> TinyWasmValue {
254+
pub(crate) fn pop_wasmvalue(&mut self, state: &crate::store::State, val_type: WasmType) -> WasmValue {
256255
match val_type {
257-
WasmType::I32 | WasmType::F32 => TinyWasmValue::Value32(Value32::stack_pop(self)),
258-
WasmType::I64 | WasmType::F64 => TinyWasmValue::Value64(Value64::stack_pop(self)),
259-
WasmType::Ref(_) => TinyWasmValue::ValueRef(ValueRef::stack_pop(self)),
260-
WasmType::V128 => TinyWasmValue::Value128(Value128::stack_pop(self)),
256+
WasmType::I32 => WasmValue::I32(self.stack_32.pop() as i32),
257+
WasmType::I64 => WasmValue::I64(self.stack_64.pop() as i64),
258+
WasmType::F32 => WasmValue::F32(f32::from_bits(self.stack_32.pop())),
259+
WasmType::F64 => WasmValue::F64(f64::from_bits(self.stack_64.pop())),
260+
WasmType::Ref(ty) => WasmValue::Ref(state.to_ref_value(ValueRef::from_raw(self.stack_32.pop()), ty)),
261+
WasmType::V128 => WasmValue::V128(self.stack_128.pop().0),
261262
}
262263
}
263264

‎crates/tinywasm/src/interpreter/values.rs‎

Lines changed: 18 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
use super::stack::{CallFrame, ValueStack};
22
use crate::store::Globals;
33
use crate::{Result, interpreter::simd::Value128};
4-
use tinywasm_types::{AnyRef, ExnRef, ExternRef, FuncRef, GlobalAddr, LocalAddr, RefValue, WasmType, WasmValue};
4+
use tinywasm_types::{GlobalAddr, LocalAddr, RefValue, WasmValue};
55

66
pub(crate) type Value32 = u32;
77
pub(crate) type Value64 = u64;
88

99
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10+
/// Packed internal representation of a WebAssembly reference.
11+
///
12+
/// Unlike the public [`RefValue`], this stores no explicit reference category.
13+
/// Converting it back therefore requires the value's canonical reference type.
1014
pub(crate) struct ValueRef(u32);
1115

1216
impl Default for ValueRef {
@@ -71,6 +75,18 @@ impl ValueRef {
7175
}
7276
}
7377

78+
impl From<RefValue> for ValueRef {
79+
fn from(value: RefValue) -> Self {
80+
match value {
81+
RefValue::Null => Self::NULL,
82+
RefValue::Func(value) => Self::from_category_addr(value.addr()),
83+
RefValue::Extern(value) => Self::from_raw(value.raw()),
84+
RefValue::Exn(value) => Self::from_category_addr(value.addr()),
85+
RefValue::Any(value) => Self::from_raw(value.raw()),
86+
}
87+
}
88+
}
89+
7490
#[allow(private_interfaces)]
7591
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7692
/// A untyped WebAssembly value
@@ -118,32 +134,6 @@ impl TinyWasmValue {
118134
_ => None,
119135
}
120136
}
121-
122-
/// Converts this internal value to the requested public WebAssembly type.
123-
pub fn attach_type(self, ty: WasmType) -> Option<WasmValue> {
124-
match (self, ty) {
125-
(Self::Value32(v), WasmType::I32) => Some(WasmValue::I32(v as i32)),
126-
(Self::Value64(v), WasmType::I64) => Some(WasmValue::I64(v as i64)),
127-
(Self::Value32(v), WasmType::F32) => Some(WasmValue::F32(f32::from_bits(v))),
128-
(Self::Value64(v), WasmType::F64) => Some(WasmValue::F64(f64::from_bits(v))),
129-
(Self::ValueRef(v), WasmType::Ref(_)) if v.is_null() => Some(RefValue::Null.into()),
130-
(Self::ValueRef(v), WasmType::Ref(ty)) if ty.is_func() => {
131-
Some(WasmValue::Ref(RefValue::Func(FuncRef::new(v.addr()?))))
132-
}
133-
(Self::ValueRef(v), WasmType::Ref(ty)) if ty.is_extern() => {
134-
Some(WasmValue::Ref(RefValue::Extern(ExternRef::from_raw(v.raw()))))
135-
}
136-
(Self::ValueRef(v), WasmType::Ref(ty)) if ty.is_exn() => {
137-
Some(WasmValue::Ref(RefValue::Exn(ExnRef::new(v.addr()?))))
138-
}
139-
(Self::ValueRef(v), WasmType::Ref(_)) => Some(WasmValue::Ref(RefValue::Any(AnyRef::from_raw(v.raw())))),
140-
(Self::Value128(v), WasmType::V128) => Some(WasmValue::V128(v.0)),
141-
(_, WasmType::I32 | WasmType::F32) => None,
142-
(_, WasmType::I64 | WasmType::F64) => None,
143-
(_, WasmType::Ref(_)) => None,
144-
(_, WasmType::V128) => None,
145-
}
146-
}
147137
}
148138

149139
impl From<&WasmValue> for TinyWasmValue {
@@ -153,11 +143,7 @@ impl From<&WasmValue> for TinyWasmValue {
153143
WasmValue::I64(v) => Self::Value64(*v as u64),
154144
WasmValue::F32(v) => Self::Value32(v.to_bits()),
155145
WasmValue::F64(v) => Self::Value64(v.to_bits()),
156-
WasmValue::Ref(RefValue::Null) => Self::ValueRef(ValueRef::NULL),
157-
WasmValue::Ref(RefValue::Func(value)) => Self::ValueRef(ValueRef::from_category_addr(value.addr())),
158-
WasmValue::Ref(RefValue::Extern(value)) => Self::ValueRef(ValueRef::from_raw(value.raw())),
159-
WasmValue::Ref(RefValue::Exn(value)) => Self::ValueRef(ValueRef::from_category_addr(value.addr())),
160-
WasmValue::Ref(RefValue::Any(value)) => Self::ValueRef(ValueRef::from_raw(value.raw())),
146+
WasmValue::Ref(value) => Self::ValueRef((*value).into()),
161147
WasmValue::V128(v) => Self::Value128((*v).into()),
162148
}
163149
}
@@ -190,9 +176,7 @@ pub(crate) trait InternalValue: sealed::Sealed + Copy + Default {
190176
fn local_set(stack: &mut ValueStack, frame: &CallFrame, index: LocalAddr, value: Self);
191177
fn local_update(stack: &mut ValueStack, frame: &CallFrame, index: LocalAddr, f: impl FnOnce(Self) -> Self);
192178
fn local_copy(stack: &mut ValueStack, frame: &CallFrame, from: LocalAddr, to: LocalAddr);
193-
/// Gets a value from its physical global lane.
194179
fn global_get(globals: &Globals, addr: GlobalAddr) -> Self;
195-
/// Sets a value in its physical global lane.
196180
fn global_set(globals: &mut Globals, addr: GlobalAddr, value: Self);
197181
}
198182

‎crates/tinywasm/src/reference.rs‎

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use alloc::format;
55
use alloc::string::{String, ToString};
66
use alloc::vec::Vec;
77

8-
use crate::interpreter::TinyWasmValue;
8+
use crate::interpreter::ValueRef;
99
use crate::store::TableInstance;
1010
use crate::{Error, MemoryInstance, Result, Store, Trap};
1111
use tinywasm_types::{Addr, GlobalType, MemAddr, MemoryType, TableAddr, TableType, WasmType, WasmValue};
@@ -347,13 +347,14 @@ fn table_value_to_element(
347347
state: &crate::store::State,
348348
element_type: tinywasm_types::RefType,
349349
value: WasmValue,
350-
) -> Result<crate::interpreter::ValueRef, Trap> {
351-
if !state.value_matches_type(value, WasmType::Ref(element_type)) {
350+
) -> Result<ValueRef, Trap> {
351+
let WasmValue::Ref(value) = value else {
352+
return Err(Trap::Other("invalid table value type"));
353+
};
354+
if !state.value_matches_type(WasmValue::Ref(value), WasmType::Ref(element_type)) {
352355
return Err(Trap::Other("invalid table value type"));
353356
}
354-
let WasmValue::Ref(value) = value else { unreachable!() };
355-
let TinyWasmValue::ValueRef(value) = TinyWasmValue::from(WasmValue::Ref(value)) else { unreachable!() };
356-
Ok(value)
357+
Ok(value.into())
357358
}
358359

359360
impl Table {
@@ -393,14 +394,9 @@ impl Table {
393394
/// Get a table element as a wasm reference value.
394395
pub fn get(&self, store: &Store, index: TableAddr) -> Result<WasmValue> {
395396
let table = self.instance(store)?;
396-
let value = store
397-
.state
398-
.attach_value(TinyWasmValue::ValueRef(*table.get(index as usize)?), WasmType::Ref(table.kind.element_type))
399-
.expect("table value matches its element type");
400-
if let WasmValue::Ref(value) = value {
401-
store.state.pin_host_ref(value);
402-
}
403-
Ok(value)
397+
let value = store.state.to_ref_value(*table.get(index as usize)?, table.kind.element_type);
398+
store.state.pin_host_ref(value);
399+
Ok(WasmValue::Ref(value))
404400
}
405401

406402
/// Load a range of table elements and iterate over wasm reference values.
@@ -413,15 +409,12 @@ impl Table {
413409
let table = self.instance(store)?;
414410
let element_type = table.kind.element_type;
415411
let elements = table.load(offset, len)?;
416-
let may_contain_gc = store.state.type_may_contain_gc(WasmType::Ref(element_type));
412+
let may_contain_gc = store.state.type_may_contain_gc(&WasmType::Ref(element_type));
417413
Ok(elements.iter().copied().map(move |value| {
418414
if may_contain_gc {
419415
store.state.gc.pin(value);
420416
}
421-
store
422-
.state
423-
.attach_value(TinyWasmValue::ValueRef(value), WasmType::Ref(element_type))
424-
.expect("table value matches its element type")
417+
WasmValue::Ref(store.state.to_ref_value(value, element_type))
425418
}))
426419
}
427420

@@ -473,7 +466,7 @@ impl Global {
473466
/// Get the current value of the global.
474467
pub fn get(&self, store: &Store) -> Result<WasmValue> {
475468
self.0.validate_store(store)?;
476-
let value = store.state.global_wasm_value(self.0.addr);
469+
let value = store.state.get_global_wasmvalue(self.0.addr);
477470
if let WasmValue::Ref(value) = value {
478471
store.state.pin_host_ref(value);
479472
}
@@ -483,6 +476,6 @@ impl Global {
483476
/// Set the current value of the global.
484477
pub fn set(&self, store: &mut Store, value: WasmValue) -> Result<()> {
485478
self.0.validate_store(store)?;
486-
store.state.set_global_wasm_value(self.0.addr, value)
479+
store.state.set_global_wasmvalue(self.0.addr, value)
487480
}
488481
}

0 commit comments

Comments
 (0)