Skip to content

Commit 31df65a

Browse files
chore: refactor executer, change the module when executing imported functions
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 2da2020 commit 31df65a

File tree

7 files changed

+72
-75
lines changed

7 files changed

+72
-75
lines changed

crates/tinywasm/src/func.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl FuncHandle {
2727

2828
// 1. Assert: funcs[func_addr] exists
2929
// 2. let func_inst be the functiuon instance funcs[func_addr]
30-
let func_inst = store.get_func(self.addr as usize)?;
30+
let func_inst = store.get_func(self.addr as usize)?.clone();
3131

3232
// 3. Let func_ty be the function type
3333
let func_ty = &self.ty;
@@ -52,26 +52,26 @@ impl FuncHandle {
5252
}
5353
}
5454

55-
let wasm_func = match &func_inst.func {
55+
let locals = match &func_inst.func {
5656
crate::Function::Host(h) => {
5757
let func = h.func.clone();
5858
let ctx = FuncContext { store, module: &self.module };
5959
return (func)(ctx, params);
6060
}
61-
crate::Function::Wasm(ref f) => f,
61+
crate::Function::Wasm(ref f) => f.locals.to_vec(),
6262
};
6363

6464
// 6. Let f be the dummy frame
65-
debug!("locals: {:?}", wasm_func.locals);
66-
let call_frame = CallFrame::new(self.addr as usize, params, wasm_func.locals.to_vec(), self.module.id());
65+
debug!("locals: {:?}", locals);
66+
let call_frame = CallFrame::new(func_inst, params, locals);
6767

6868
// 7. Push the frame f to the call stack
6969
// & 8. Push the values to the stack (Not needed since the call frame owns the values)
7070
stack.call_stack.push(call_frame)?;
7171

7272
// 9. Invoke the function instance
7373
let runtime = store.runtime();
74-
runtime.exec(store, &mut stack, self.module.clone())?;
74+
runtime.exec(store, &mut stack)?;
7575

7676
// Once the function returns:
7777
let result_m = func_ty.results.len();

crates/tinywasm/src/instance.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl ModuleInstance {
8181
mem_addrs: addrs.memories.into_boxed_slice(),
8282
global_addrs: addrs.globals.into_boxed_slice(),
8383
elem_addrs,
84-
data_addrs: data_addrs,
84+
data_addrs,
8585
func_start: data.start_func,
8686
imports: data.imports,
8787
exports: data.exports,
@@ -111,11 +111,7 @@ impl ModuleInstance {
111111
&self.0.func_addrs
112112
}
113113

114-
pub(crate) fn _global_addrs(&self) -> &[GlobalAddr] {
115-
&self.0.global_addrs
116-
}
117-
118-
pub(crate) fn func_ty_addrs(&self) -> &[FuncType] {
114+
pub(crate) fn func_tys(&self) -> &[FuncType] {
119115
&self.0.types
120116
}
121117

crates/tinywasm/src/runtime/executor/mod.rs

Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,32 @@ use macros::*;
1515
use traits::*;
1616

1717
impl DefaultRuntime {
18-
pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack, module: ModuleInstance) -> Result<()> {
19-
log::debug!("func_addrs: {:?}", module.func_addrs());
20-
log::debug!("func_ty_addrs: {:?}", module.func_ty_addrs().len());
21-
log::debug!("store funcs: {:?}", store.data.funcs.len());
22-
18+
pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack) -> Result<()> {
2319
// The current call frame, gets updated inside of exec_one
2420
let mut cf = stack.call_stack.pop()?;
2521

26-
// The function to execute, gets updated from ExecResult::Call
27-
let mut func_inst = store.get_func(cf.func_ptr)?.clone();
22+
let mut func_inst = cf.func_instance.clone();
2823
let mut wasm_func = func_inst.assert_wasm().expect("exec expected wasm function");
24+
25+
// The function to execute, gets updated from ExecResult::Call
2926
let mut instrs = &wasm_func.instructions;
3027

31-
let mut current_module = module;
28+
let mut current_module = store
29+
.get_module_instance(func_inst.owner)
30+
.expect("exec expected module instance to exist for function")
31+
.clone();
3232

3333
while let Some(instr) = instrs.get(cf.instr_ptr) {
3434
match exec_one(&mut cf, instr, instrs, stack, store, &current_module)? {
3535
// Continue execution at the new top of the call stack
3636
ExecResult::Call => {
3737
cf = stack.call_stack.pop()?;
38-
func_inst = store.get_func(cf.func_ptr)?.clone();
39-
wasm_func = func_inst.assert_wasm().expect("call expected wasm function");
38+
func_inst = cf.func_instance.clone();
39+
wasm_func = func_inst.assert_wasm().expect("exec expected wasm function");
4040
instrs = &wasm_func.instructions;
4141

42-
if cf.module != current_module.id() {
43-
current_module.swap(store.get_module_instance(cf.module).unwrap().clone());
42+
if cf.func_instance.owner != current_module.id() {
43+
current_module.swap(store.get_module_instance(cf.func_instance.owner).unwrap().clone());
4444
}
4545

4646
continue;
@@ -135,10 +135,10 @@ fn exec_one(
135135
log::info!("start call");
136136
// prepare the call frame
137137
let func_idx = module.resolve_func_addr(*v);
138-
let func_inst = store.get_func(func_idx as usize)?;
138+
let func_inst = store.get_func(func_idx as usize)?.clone();
139139

140-
let func = match &func_inst.func {
141-
crate::Function::Wasm(ref f) => f,
140+
let (locals, ty) = match &func_inst.func {
141+
crate::Function::Wasm(ref f) => (f.locals.to_vec(), f.ty.clone()),
142142
crate::Function::Host(host_func) => {
143143
let func = host_func.func.clone();
144144
log::info!("Getting params: {:?}", host_func.ty.params);
@@ -150,8 +150,11 @@ fn exec_one(
150150
}
151151
};
152152

153-
let params = stack.values.pop_n_rev(func.ty.params.len())?;
154-
let call_frame = CallFrame::new_raw(func_idx as usize, &params, func.locals.to_vec(), func_inst._owner);
153+
let params = stack.values.pop_n_rev(ty.params.len())?;
154+
log::info!("call: current fn owner: {:?}", module.id());
155+
log::info!("call: func owner: {:?}", func_inst.owner);
156+
157+
let call_frame = CallFrame::new_raw(func_inst, &params, locals);
155158

156159
// push the call frame
157160
cf.instr_ptr += 1; // skip the call instruction
@@ -163,29 +166,39 @@ fn exec_one(
163166
}
164167

165168
CallIndirect(type_addr, table_addr) => {
166-
let table_idx = module.resolve_table_addr(*table_addr);
167-
let table = store.get_table(table_idx as usize)?;
168-
169-
// TODO: currently, the type resolution is subtlely broken for imported functions
170-
171-
let call_ty = module.func_ty(*type_addr);
172-
173-
let func_idx = stack.values.pop_t::<u32>()?;
169+
let table = store.get_table(module.resolve_table_addr(*table_addr) as usize)?;
170+
let table_idx = stack.values.pop_t::<u32>()?;
174171

175172
// verify that the table is of the right type, this should be validated by the parser already
176173
assert!(table.borrow().kind.element_type == ValType::RefFunc, "table is not of type funcref");
177174

178-
let func_ref = table
179-
.borrow()
180-
.get(func_idx as usize)?
181-
.addr()
182-
.ok_or_else(|| Trap::UninitializedElement { index: func_idx as usize })?;
175+
let func_ref = {
176+
table
177+
.borrow()
178+
.get(table_idx as usize)?
179+
.addr()
180+
.ok_or(Trap::UninitializedElement { index: table_idx as usize })?
181+
};
183182

184-
let func_inst = store.get_func(func_ref as usize)?;
183+
let func_inst = store.get_func(func_ref as usize)?.clone();
185184
let func_ty = func_inst.func.ty();
186185

187-
let func = match &func_inst.func {
188-
crate::Function::Wasm(ref f) => f,
186+
log::info!("type_addr: {}", type_addr);
187+
log::info!("types: {:?}", module.func_tys());
188+
let call_ty = module.func_ty(*type_addr);
189+
190+
log::info!("call_indirect: current fn owner: {:?}", module.id());
191+
log::info!("call_indirect: func owner: {:?}", func_inst.owner);
192+
193+
if func_ty != call_ty {
194+
log::error!("indirect call type mismatch: {:?} != {:?}", func_ty, call_ty);
195+
return Err(
196+
Trap::IndirectCallTypeMismatch { actual: func_ty.clone(), expected: call_ty.clone() }.into()
197+
);
198+
}
199+
200+
let locals = match &func_inst.func {
201+
crate::Function::Wasm(ref f) => f.locals.to_vec(),
189202
crate::Function::Host(host_func) => {
190203
let func = host_func.func.clone();
191204
let params = stack.values.pop_params(&func_ty.params)?;
@@ -195,14 +208,8 @@ fn exec_one(
195208
}
196209
};
197210

198-
if func_ty != call_ty {
199-
return Err(
200-
Trap::IndirectCallTypeMismatch { actual: func_ty.clone(), expected: call_ty.clone() }.into()
201-
);
202-
}
203-
204211
let params = stack.values.pop_n_rev(func_ty.params.len())?;
205-
let call_frame = CallFrame::new_raw(func_ref as usize, &params, func.locals.to_vec(), func_inst._owner);
212+
let call_frame = CallFrame::new_raw(func_inst, &params, locals);
206213

207214
// push the call frame
208215
cf.instr_ptr += 1; // skip the call instruction

crates/tinywasm/src/runtime/stack/call_stack.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use crate::{runtime::RawWasmValue, BlockType, Error, LabelFrame, Result, Trap};
2-
use alloc::{boxed::Box, vec::Vec};
3-
use tinywasm_types::{ModuleInstanceAddr, ValType, WasmValue};
1+
use crate::{runtime::RawWasmValue, BlockType, Error, FunctionInstance, LabelFrame, Result, Trap};
2+
use alloc::{boxed::Box, rc::Rc, vec::Vec};
3+
use tinywasm_types::{ValType, WasmValue};
44

55
use super::blocks::Labels;
66

@@ -52,9 +52,9 @@ impl CallStack {
5252

5353
#[derive(Debug, Clone)]
5454
pub(crate) struct CallFrame {
55-
pub(crate) module: ModuleInstanceAddr,
5655
pub(crate) instr_ptr: usize,
57-
pub(crate) func_ptr: usize,
56+
// pub(crate) module: ModuleInstanceAddr,
57+
pub(crate) func_instance: Rc<FunctionInstance>,
5858

5959
pub(crate) labels: Labels,
6060
pub(crate) locals: Box<[RawWasmValue]>,
@@ -109,36 +109,32 @@ impl CallFrame {
109109
}
110110

111111
pub(crate) fn new_raw(
112-
func_ptr: usize,
112+
func_instance_ptr: Rc<FunctionInstance>,
113113
params: &[RawWasmValue],
114114
local_types: Vec<ValType>,
115-
module: ModuleInstanceAddr,
116115
) -> Self {
117116
let mut locals = Vec::with_capacity(local_types.len() + params.len());
118117
locals.extend(params.iter().cloned());
119118
locals.extend(local_types.iter().map(|_| RawWasmValue::default()));
120119

121120
Self {
122121
instr_ptr: 0,
123-
func_ptr,
122+
func_instance: func_instance_ptr,
124123
local_count: locals.len(),
125124
locals: locals.into_boxed_slice(),
126125
labels: Labels::default(),
127-
module,
128126
}
129127
}
130128

131129
pub(crate) fn new(
132-
func_ptr: usize,
130+
func_instance_ptr: Rc<FunctionInstance>,
133131
params: &[WasmValue],
134132
local_types: Vec<ValType>,
135-
module: ModuleInstanceAddr,
136133
) -> Self {
137134
CallFrame::new_raw(
138-
func_ptr,
135+
func_instance_ptr,
139136
&params.iter().map(|v| RawWasmValue::from(*v)).collect::<Vec<_>>(),
140137
local_types,
141-
module,
142138
)
143139
}
144140

crates/tinywasm/src/store.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl Store {
121121
self.data.funcs.push(Rc::new(FunctionInstance {
122122
func: Function::Wasm(func),
123123
_type_idx: type_idx,
124-
_owner: idx,
124+
owner: idx,
125125
}));
126126
func_addrs.push((i + func_count) as FuncAddr);
127127
}
@@ -303,7 +303,7 @@ impl Store {
303303
}
304304

305305
pub(crate) fn add_func(&mut self, func: Function, type_idx: TypeAddr, idx: ModuleInstanceAddr) -> Result<FuncAddr> {
306-
self.data.funcs.push(Rc::new(FunctionInstance { func, _type_idx: type_idx, _owner: idx }));
306+
self.data.funcs.push(Rc::new(FunctionInstance { func, _type_idx: type_idx, owner: idx }));
307307
Ok(self.data.funcs.len() as FuncAddr - 1)
308308
}
309309

@@ -388,7 +388,7 @@ impl Store {
388388
pub struct FunctionInstance {
389389
pub(crate) func: Function,
390390
pub(crate) _type_idx: TypeAddr,
391-
pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions
391+
pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions
392392
}
393393

394394
// TODO: check if this actually helps
@@ -442,10 +442,8 @@ impl TableInstance {
442442
let val = self.get(addr)?.addr();
443443

444444
Ok(match self.kind.element_type {
445-
ValType::RefFunc => val.map(|v| WasmValue::RefFunc(v)).unwrap_or(WasmValue::RefNull(ValType::RefFunc)),
446-
ValType::RefExtern => {
447-
val.map(|v| WasmValue::RefExtern(v)).unwrap_or(WasmValue::RefNull(ValType::RefExtern))
448-
}
445+
ValType::RefFunc => val.map(WasmValue::RefFunc).unwrap_or(WasmValue::RefNull(ValType::RefFunc)),
446+
ValType::RefExtern => val.map(WasmValue::RefExtern).unwrap_or(WasmValue::RefNull(ValType::RefExtern)),
449447
_ => unimplemented!("unsupported table type: {:?}", self.kind.element_type),
450448
})
451449
}

0 commit comments

Comments
 (0)