Skip to content

Commit 430ea40

Browse files
chore: atomic module data
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 9d19098 commit 430ea40

File tree

16 files changed

+189
-159
lines changed

16 files changed

+189
-159
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ flamegraph.svg
99
/.idea
1010
/*.iml
1111
profile.json
12+
profile.json.gz

crates/parser/src/module.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
use crate::log::debug;
22
use crate::{ParseError, Result, conversion};
33
use alloc::string::ToString;
4-
use alloc::{boxed::Box, format, vec::Vec};
4+
use alloc::sync::Arc;
5+
use alloc::{format, vec::Vec};
56
use tinywasm_types::{
6-
Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, TinyWasmModule, ValueCounts,
7-
ValueCountsSmall, WasmFunction, WasmFunctionData,
7+
ArcSlice, Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, TinyWasmModule,
8+
ValueCounts, ValueCountsSmall, WasmFunction, WasmFunctionData,
89
};
910
use wasmparser::{FuncValidatorAllocations, Payload, Validator};
1011

11-
pub(crate) type Code = (Box<[Instruction]>, WasmFunctionData, ValueCounts);
12+
pub(crate) type Code = (Arc<[Instruction]>, WasmFunctionData, ValueCounts);
1213

1314
#[derive(Default)]
1415
pub(crate) struct ModuleReader {
@@ -195,25 +196,24 @@ impl ModuleReader {
195196
.map(|((instructions, data, locals), ty_idx)| {
196197
let ty = self.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone();
197198
let params = ValueCountsSmall::from(&ty.params);
198-
WasmFunction { instructions, data, locals, params, ty }
199+
WasmFunction { instructions: ArcSlice(instructions), data, locals, params, ty }
199200
})
200-
.collect::<Vec<_>>()
201-
.into_boxed_slice();
201+
.collect::<Vec<_>>();
202202

203203
let globals = self.globals;
204204
let table_types = self.table_types;
205205

206206
Ok(TinyWasmModule {
207-
funcs,
208-
func_types: self.func_types.into_boxed_slice(),
209-
globals: globals.into_boxed_slice(),
210-
table_types: table_types.into_boxed_slice(),
211-
imports: self.imports.into_boxed_slice(),
207+
funcs: funcs.into(),
208+
func_types: self.func_types.into(),
209+
globals: globals.into(),
210+
table_types: table_types.into(),
211+
imports: self.imports.into(),
212212
start_func: self.start_func,
213-
data: self.data.into_boxed_slice(),
214-
exports: self.exports.into_boxed_slice(),
215-
elements: self.elements.into_boxed_slice(),
216-
memory_types: self.memory_types.into_boxed_slice(),
213+
data: self.data.into(),
214+
exports: self.exports.into(),
215+
elements: self.elements.into(),
216+
memory_types: self.memory_types.into(),
217217
})
218218
}
219219
}

crates/parser/src/visit.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::Result;
22

33
use crate::conversion::{convert_heaptype, convert_valtype};
44
use alloc::string::ToString;
5-
use alloc::{boxed::Box, vec::Vec};
5+
use alloc::vec::Vec;
66
use tinywasm_types::{Instruction, MemoryArg, WasmFunctionData};
77
use wasmparser::{
88
FuncValidator, FuncValidatorAllocations, FunctionBody, VisitOperator, VisitSimdOperator, WasmModuleResources,
@@ -37,7 +37,7 @@ pub(crate) fn process_operators_and_validate<R: WasmModuleResources>(
3737
validator: FuncValidator<R>,
3838
body: FunctionBody<'_>,
3939
local_addr_map: Vec<u32>,
40-
) -> Result<(Box<[Instruction]>, WasmFunctionData, FuncValidatorAllocations)> {
40+
) -> Result<(alloc::sync::Arc<[Instruction]>, WasmFunctionData, FuncValidatorAllocations)> {
4141
let mut reader = body.get_operators_reader()?;
4242
let remaining = reader.get_binary_reader().bytes_remaining();
4343
let mut builder = FunctionBuilder::new(remaining, validator, local_addr_map);
@@ -52,7 +52,7 @@ pub(crate) fn process_operators_and_validate<R: WasmModuleResources>(
5252
}
5353

5454
Ok((
55-
builder.instructions.into_boxed_slice(),
55+
alloc::sync::Arc::from(builder.instructions),
5656
WasmFunctionData { v128_constants: builder.v128_constants.into_boxed_slice() },
5757
builder.validator.into_allocations(),
5858
))

crates/tinywasm/src/func.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ impl FuncHandle {
6060

6161
// 7. Push the frame f to the call stack
6262
// & 8. Push the values to the stack (Not needed since the call frame owns the values)
63-
store.stack.initialize(callframe);
63+
store.stack.clear();
6464

6565
// 9. Invoke the function instance
66-
InterpreterRuntime::exec(store)?;
66+
InterpreterRuntime::exec(store, callframe)?;
6767

6868
// Once the function returns:
6969
// 1. Assert: m values are on the top of the stack (Ensured by validation)

crates/tinywasm/src/imports.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ impl Imports {
363363
) -> Result<ResolvedImports> {
364364
let mut imports = ResolvedImports::new();
365365

366-
for import in &module.0.imports {
366+
for import in &*module.0.imports {
367367
let val = self.take(store, import).ok_or_else(|| LinkingError::unknown_import(import))?;
368368

369369
match val {

crates/tinywasm/src/instance.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use alloc::{boxed::Box, format, rc::Rc};
1+
use alloc::boxed::Box;
2+
use alloc::{format, rc::Rc};
23
use tinywasm_types::*;
34

45
use crate::func::{FromWasmValueTuple, IntoWasmValueTuple};
@@ -20,7 +21,7 @@ pub(crate) struct ModuleInstanceInner {
2021
pub(crate) store_id: usize,
2122
pub(crate) idx: ModuleInstanceAddr,
2223

23-
pub(crate) types: Box<[FuncType]>,
24+
pub(crate) types: ArcSlice<FuncType>,
2425

2526
pub(crate) func_addrs: Box<[FuncAddr]>,
2627
pub(crate) table_addrs: Box<[TableAddr]>,
@@ -30,8 +31,8 @@ pub(crate) struct ModuleInstanceInner {
3031
pub(crate) data_addrs: Box<[DataAddr]>,
3132

3233
pub(crate) func_start: Option<FuncAddr>,
33-
pub(crate) imports: Box<[Import]>,
34-
pub(crate) exports: Box<[Export]>,
34+
pub(crate) imports: ArcSlice<Import>,
35+
pub(crate) exports: ArcSlice<Export>,
3536
}
3637

3738
impl ModuleInstance {
@@ -65,29 +66,29 @@ impl ModuleInstance {
6566
let idx = store.next_module_instance_idx();
6667
let mut addrs = imports.unwrap_or_default().link(store, &module, idx)?;
6768

68-
addrs.funcs.extend(store.init_funcs(module.0.funcs.into(), idx)?);
69-
addrs.tables.extend(store.init_tables(module.0.table_types.into(), idx)?);
70-
addrs.memories.extend(store.init_memories(module.0.memory_types.into(), idx)?);
69+
addrs.funcs.extend(store.init_funcs(&module.0.funcs, idx)?);
70+
addrs.tables.extend(store.init_tables(&module.0.table_types, idx)?);
71+
addrs.memories.extend(store.init_memories(&module.0.memory_types, idx)?);
7172

72-
let global_addrs = store.init_globals(addrs.globals, module.0.globals.into(), &addrs.funcs, idx)?;
73+
let global_addrs = store.init_globals(addrs.globals, &module.0.globals, &addrs.funcs, idx)?;
7374
let (elem_addrs, elem_trapped) =
7475
store.init_elements(&addrs.tables, &addrs.funcs, &global_addrs, &module.0.elements, idx)?;
75-
let (data_addrs, data_trapped) = store.init_data(&addrs.memories, module.0.data.into(), idx)?;
76+
let (data_addrs, data_trapped) = store.init_data(&addrs.memories, &module.0.data, idx)?;
7677

7778
let instance = ModuleInstanceInner {
7879
failed_to_instantiate: elem_trapped.is_some() || data_trapped.is_some(),
7980
store_id: store.id(),
8081
idx,
81-
types: module.0.func_types,
82+
types: module.0.func_types.clone(),
8283
func_addrs: addrs.funcs.into_boxed_slice(),
8384
table_addrs: addrs.tables.into_boxed_slice(),
8485
mem_addrs: addrs.memories.into_boxed_slice(),
8586
global_addrs: global_addrs.into_boxed_slice(),
8687
elem_addrs,
8788
data_addrs,
8889
func_start: module.0.start_func,
89-
imports: module.0.imports,
90-
exports: module.0.exports,
90+
imports: module.0.imports.clone(),
91+
exports: module.0.exports.clone(),
9192
};
9293

9394
let instance = Self::new(instance);

crates/tinywasm/src/interpreter/executor.rs

Lines changed: 37 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,9 @@ pub(crate) struct Executor<'store> {
2222
}
2323

2424
impl<'store> Executor<'store> {
25-
pub(crate) fn new(store: &'store mut Store) -> Result<Self> {
26-
let current_frame = store.stack.call_stack.pop().expect("no call frame, this is a bug");
27-
let current_module = store.get_module_instance_raw(current_frame.module_addr());
28-
Ok(Self { cf: current_frame, module: current_module, store })
25+
pub(crate) fn new(store: &'store mut Store, cf: CallFrame) -> Result<Self> {
26+
let module = store.get_module_instance_raw(cf.module_addr());
27+
Ok(Self { module, store, cf })
2928
}
3029

3130
pub(crate) fn run_to_completion(&mut self) -> Result<()> {
@@ -104,22 +103,22 @@ impl<'store> Executor<'store> {
104103
BrTable(default, len) => return self.exec_brtable(*default, *len),
105104
Return => return self.exec_return(),
106105
EndBlockFrame => self.exec_end_block(),
107-
LocalGet32(local_index) => self.exec_local_get::<Value32>(*local_index),
108-
LocalGet64(local_index) => self.exec_local_get::<Value64>(*local_index),
109-
LocalGet128(local_index) => self.exec_local_get::<Value128>(*local_index),
110-
LocalGetRef(local_index) => self.exec_local_get::<ValueRef>(*local_index),
111-
LocalSet32(local_index) => self.exec_local_set::<Value32>(*local_index),
112-
LocalSet64(local_index) => self.exec_local_set::<Value64>(*local_index),
113-
LocalSet128(local_index) => self.exec_local_set::<Value128>(*local_index),
114-
LocalSetRef(local_index) => self.exec_local_set::<ValueRef>(*local_index),
115-
LocalCopy32(from, to) => self.exec_local_copy::<Value32>(*from, *to),
116-
LocalCopy64(from, to) => self.exec_local_copy::<Value64>(*from, *to),
117-
LocalCopy128(from, to) => self.exec_local_copy::<Value128>(*from, *to),
118-
LocalCopyRef(from, to) => self.exec_local_copy::<ValueRef>(*from, *to),
119-
LocalTee32(local_index) => self.exec_local_tee::<Value32>(*local_index),
120-
LocalTee64(local_index) => self.exec_local_tee::<Value64>(*local_index),
121-
LocalTee128(local_index) => self.exec_local_tee::<Value128>(*local_index),
122-
LocalTeeRef(local_index) => self.exec_local_tee::<ValueRef>(*local_index),
106+
LocalGet32(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value32>(*local_index)),
107+
LocalGet64(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value64>(*local_index)),
108+
LocalGet128(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value128>(*local_index)),
109+
LocalGetRef(local_index) => self.store.stack.values.push(self.cf.locals.get::<ValueRef>(*local_index)),
110+
LocalSet32(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value32>()),
111+
LocalSet64(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value64>()),
112+
LocalSet128(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value128>()),
113+
LocalSetRef(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<ValueRef>()),
114+
LocalCopy32(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value32>(*from)),
115+
LocalCopy64(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value64>(*from)),
116+
LocalCopy128(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value128>(*from)),
117+
LocalCopyRef(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<ValueRef>(*from)),
118+
LocalTee32(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value32>()),
119+
LocalTee64(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value64>()),
120+
LocalTee128(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value128>()),
121+
LocalTeeRef(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<ValueRef>()),
123122
GlobalGet(global_index) => self.exec_global_get(*global_index),
124123
GlobalSet32(global_index) => self.exec_global_set::<Value32>(*global_index),
125124
GlobalSet64(global_index) => self.exec_global_set::<Value64>(*global_index),
@@ -567,11 +566,11 @@ impl<'store> Executor<'store> {
567566
wasm_func: Rc<WasmFunction>,
568567
owner: ModuleInstanceAddr,
569568
) -> ControlFlow<Option<Error>> {
570-
let locals = self.store.stack.values.pop_locals(wasm_func.params, wasm_func.locals);
571-
572569
if IS_RETURN_CALL {
570+
let locals = self.store.stack.values.pop_locals(wasm_func.params, wasm_func.locals);
573571
self.cf.reuse_for(wasm_func, locals, self.store.stack.blocks.len() as u32, owner);
574572
} else {
573+
let locals = self.store.stack.values.pop_locals(wasm_func.params, wasm_func.locals);
575574
let new_call_frame = CallFrame::new_raw(wasm_func, owner, locals, self.store.stack.blocks.len() as u32);
576575
self.cf.incr_instr_ptr(); // skip the call instruction
577576
self.store.stack.call_stack.push(core::mem::replace(&mut self.cf, new_call_frame))?;
@@ -580,7 +579,7 @@ impl<'store> Executor<'store> {
580579
self.module.swap_with(self.cf.module_addr(), self.store);
581580
ControlFlow::Continue(())
582581
}
583-
fn exec_call_host(&mut self, host_func: &Rc<imports::HostFunction>) -> ControlFlow<Option<Error>> {
582+
fn exec_call_host(&mut self, host_func: Rc<imports::HostFunction>) -> ControlFlow<Option<Error>> {
584583
let params = self.store.stack.values.pop_types(&host_func.ty.params).collect::<Box<_>>();
585584
let res = host_func.call(FuncContext { store: self.store, module_addr: self.module.id() }, &params).to_cf()?;
586585
self.store.stack.values.extend_from_wasmvalues(&res);
@@ -589,9 +588,9 @@ impl<'store> Executor<'store> {
589588
}
590589
fn exec_call_direct<const IS_RETURN_CALL: bool>(&mut self, v: u32) -> ControlFlow<Option<Error>> {
591590
let func_inst = self.store.state.get_func(self.module.resolve_func_addr(v));
592-
match func_inst.func.clone() {
593-
crate::Function::Wasm(wasm_func) => self.exec_call::<IS_RETURN_CALL>(wasm_func, func_inst.owner),
594-
crate::Function::Host(host_func) => self.exec_call_host(&host_func),
591+
match &func_inst.func {
592+
crate::Function::Wasm(wasm_func) => self.exec_call::<IS_RETURN_CALL>(wasm_func.clone(), func_inst.owner),
593+
crate::Function::Host(host_func) => self.exec_call_host(host_func.clone()),
595594
}
596595
}
597596
fn exec_call_indirect<const IS_RETURN_CALL: bool>(
@@ -612,26 +611,26 @@ impl<'store> Executor<'store> {
612611
let func_inst = self.store.state.get_func(func_ref);
613612
let call_ty = self.module.func_ty(type_addr);
614613

615-
match func_inst.func.clone() {
614+
match &func_inst.func {
616615
crate::Function::Wasm(wasm_func) => {
617-
if unlikely(wasm_func.ty != *call_ty) {
616+
if wasm_func.ty != *call_ty {
618617
return ControlFlow::Break(Some(
619618
Trap::IndirectCallTypeMismatch { actual: wasm_func.ty.clone(), expected: call_ty.clone() }
620619
.into(),
621620
));
622621
}
623622

624-
self.exec_call::<IS_RETURN_CALL>(wasm_func, func_inst.owner)
623+
self.exec_call::<IS_RETURN_CALL>(wasm_func.clone(), func_inst.owner)
625624
}
626625
crate::Function::Host(host_func) => {
627-
if unlikely(host_func.ty != *call_ty) {
626+
if host_func.ty != *call_ty {
628627
return ControlFlow::Break(Some(
629628
Trap::IndirectCallTypeMismatch { actual: host_func.ty.clone(), expected: call_ty.clone() }
630629
.into(),
631630
));
632631
}
633632

634-
self.exec_call_host(&host_func)
633+
self.exec_call_host(host_func.clone())
635634
}
636635
}
637636
}
@@ -645,24 +644,24 @@ impl<'store> Executor<'store> {
645644

646645
// falsy value is on the top of the stack
647646
if else_offset == 0 {
648-
self.cf.jump(end_offset as usize);
647+
self.cf.jump(end_offset);
649648
return;
650649
}
651650

652-
self.cf.jump(else_offset as usize);
651+
self.cf.jump(else_offset);
653652
self.enter_block(end_offset - else_offset, BlockType::Else, (params, results));
654653
}
655654
fn exec_else(&mut self, end_offset: u32) {
656655
self.exec_end_block();
657-
self.cf.jump(end_offset as usize);
656+
self.cf.jump(end_offset);
658657
}
659658
fn resolve_functype(&self, idx: u32) -> (StackHeight, StackHeight) {
660659
let ty = self.module.func_ty(idx);
661660
((&*ty.params).into(), (&*ty.results).into())
662661
}
663662
fn enter_block(&mut self, end_instr_offset: u32, ty: BlockType, (params, results): (StackHeight, StackHeight)) {
664663
self.store.stack.blocks.push(BlockFrame {
665-
instr_ptr: self.cf.instr_ptr(),
664+
instr_ptr: self.cf.instr_ptr() as u32,
666665
end_instr_offset,
667666
stack_ptr: self.store.stack.values.height(),
668667
results,
@@ -730,18 +729,6 @@ impl<'store> Executor<'store> {
730729
let block = self.store.stack.blocks.pop();
731730
self.store.stack.values.truncate_keep(block.stack_ptr, block.results);
732731
}
733-
fn exec_local_get<T: InternalValue>(&mut self, local_index: u16) {
734-
let v = self.cf.locals.get::<T>(local_index);
735-
self.store.stack.values.push(v);
736-
}
737-
fn exec_local_set<T: InternalValue>(&mut self, local_index: u16) {
738-
let v = self.store.stack.values.pop::<T>();
739-
self.cf.locals.set(local_index, v);
740-
}
741-
fn exec_local_tee<T: InternalValue>(&mut self, local_index: u16) {
742-
let v = self.store.stack.values.peek::<T>();
743-
self.cf.locals.set(local_index, v);
744-
}
745732

746733
fn exec_global_get(&mut self, global_index: u32) {
747734
self.store
@@ -830,7 +817,7 @@ impl<'store> Executor<'store> {
830817

831818
let data_len = data.data.as_ref().map_or(0, |d| d.len());
832819

833-
if unlikely(((size + offset) as usize > data_len) || ((dst + size) as usize > mem.len())) {
820+
if ((size + offset) as usize > data_len) || ((dst + size) as usize > mem.len()) {
834821
return Err(Trap::MemoryOutOfBounds { offset: offset as usize, len: size as usize, max: data_len }.into());
835822
}
836823

@@ -999,7 +986,7 @@ impl<'store> Executor<'store> {
999986
let elem_len = elem.items.as_ref().map_or(0, alloc::vec::Vec::len);
1000987
let table_len = table.size();
1001988

1002-
if unlikely(size < 0 || ((size + offset) as usize > elem_len) || ((dst + size) > table_len)) {
989+
if size < 0 || ((size + offset) as usize > elem_len) || ((dst + size) > table_len) {
1003990
return Err(Trap::TableOutOfBounds { offset: offset as usize, len: size as usize, max: elem_len }.into());
1004991
}
1005992

@@ -1038,7 +1025,7 @@ impl<'store> Executor<'store> {
10381025
let val = self.store.stack.values.pop::<ValueRef>();
10391026
let i = self.store.stack.values.pop::<i32>();
10401027

1041-
if unlikely(i + n > table.size()) {
1028+
if i + n > table.size() {
10421029
return Err(Error::Trap(Trap::TableOutOfBounds {
10431030
offset: i as usize,
10441031
len: n as usize,
@@ -1052,9 +1039,4 @@ impl<'store> Executor<'store> {
10521039

10531040
table.fill(self.module.func_addrs(), i as usize, n as usize, val.into())
10541041
}
1055-
1056-
fn exec_local_copy<T: InternalValue>(&mut self, from: u16, to: u16) {
1057-
let v = self.cf.locals.get::<T>(from);
1058-
self.cf.locals.set(to, v);
1059-
}
10601042
}

0 commit comments

Comments
 (0)