Skip to content

Commit 0d82700

Browse files
create enum to distinguish between owned/imported wasm funcs & memory related micro optimizations
1 parent 6a4c62b commit 0d82700

4 files changed

Lines changed: 94 additions & 97 deletions

File tree

Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ paste = "1.0.15"
1313
clap = { version = "4", features = ["derive"] }
1414
nohash-hasher = "0.2"
1515

16+
[profile.release]
17+
opt-level = 3
18+
lto = "thin"
19+
codegen-units = 1
20+
panic = "abort"
21+
overflow-checks = false
22+
1623
[[bin]]
1724
name = "wagmi-run"
1825
path = "src/bin/wagmi_run.rs"

src/instance.rs

Lines changed: 75 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -251,13 +251,15 @@ pub struct WasmGlobal {
251251

252252
#[derive(Clone)]
253253
pub enum RuntimeFunction {
254-
Wasm {
254+
OwnedWasm {
255255
runtime_sig: RuntimeSignature,
256256
pc_start: usize,
257257
locals_count: usize,
258-
// For cross-instance calls, weak is to avoid cycles
259-
owner: Option<Weak<Instance>>,
260-
function_index: Option<usize>,
258+
},
259+
ImportedWasm {
260+
runtime_sig: RuntimeSignature,
261+
owner: Weak<Instance>,
262+
function_index: usize,
261263
},
262264
Host {
263265
callback: Rc<dyn Fn(&[WasmValue]) -> Option<WasmValue>>,
@@ -268,7 +270,8 @@ pub enum RuntimeFunction {
268270
impl RuntimeFunction {
269271
pub fn signature(&self) -> RuntimeSignature {
270272
match self {
271-
RuntimeFunction::Wasm { runtime_sig, .. } => *runtime_sig,
273+
RuntimeFunction::OwnedWasm { runtime_sig, .. } => *runtime_sig,
274+
RuntimeFunction::ImportedWasm { runtime_sig, .. } => *runtime_sig,
272275
RuntimeFunction::Host { runtime_sig, .. } => *runtime_sig,
273276
}
274277
}
@@ -391,12 +394,10 @@ impl Instance {
391394
}
392395
} else {
393396
let locals_count = function.locals.len().saturating_sub(function.ty.params.len());
394-
inst.functions.push(RuntimeFunction::Wasm {
397+
inst.functions.push(RuntimeFunction::OwnedWasm {
395398
runtime_sig: RuntimeSignature::from_signature(&function.ty),
396399
pc_start: function.body.start,
397-
locals_count,
398-
owner: None,
399-
function_index: None
400+
locals_count,
400401
});
401402
}
402403
}
@@ -481,18 +482,10 @@ impl Instance {
481482
let func_idx = *idx as usize;
482483
let f = inst.functions[func_idx].clone();
483484
let (owner_id, owner_func_idx) = match &f {
484-
RuntimeFunction::Wasm { owner, function_index: owner_idx, .. } => {
485-
if let (Some(weak_owner), Some(idx)) = (owner, owner_idx) {
486-
if let Some(owner_rc) = weak_owner.upgrade() {
487-
(owner_rc.id, *idx as u32)
488-
} else {
489-
(inst.id, func_idx as u32)
490-
}
491-
} else {
492-
(inst.id, func_idx as u32)
493-
}
485+
RuntimeFunction::ImportedWasm { owner, function_index, .. } => {
486+
if let Some(owner_rc) = owner.upgrade() { (owner_rc.id, *function_index as u32) } else { (inst.id, func_idx as u32) }
494487
}
495-
RuntimeFunction::Host { .. } => (inst.id, func_idx as u32),
488+
RuntimeFunction::OwnedWasm { .. } | RuntimeFunction::Host { .. } => (inst.id, func_idx as u32),
496489
};
497490
let func_ref = FuncRef::new(owner_id, owner_func_idx);
498491
let func_ref_value = WasmValue::from_u64(func_ref.as_raw());
@@ -508,9 +501,7 @@ impl Instance {
508501
if !pending.is_empty() {
509502
let mut m = mem.borrow_mut();
510503
for (offset, bytes_vec) in pending.into_iter() {
511-
for (i, b) in bytes_vec.iter().enumerate() {
512-
m.store_u8(offset + i as u32, 0, *b).map_err(Error::Trap)?;
513-
}
504+
m.write_bytes(offset, &bytes_vec).map_err(Error::Trap)?;
514505
}
515506
}
516507
}
@@ -649,17 +640,15 @@ impl Instance {
649640
}
650641
let fi = &self.functions[idx];
651642
match fi {
652-
RuntimeFunction::Wasm { runtime_sig, pc_start, locals_count, owner, function_index: owner_idx } => {
653-
if let (Some(owner_weak), Some(owner_idx)) = (owner, owner_idx) {
654-
// Cross-instance call
655-
if let Some(owner_rc) = owner_weak.upgrade() {
656-
owner_rc.call_function_idx(*owner_idx, return_pc, stack, control, func_bases, ctrl_bases)?;
657-
} else {
658-
return Err(Error::Trap(FUNC_NO_IMPL));
659-
}
643+
RuntimeFunction::OwnedWasm { runtime_sig, pc_start, locals_count } => {
644+
let pc = Self::setup_wasm_function_call(*runtime_sig, *pc_start, *locals_count, stack, control, func_bases, ctrl_bases, *return_pc)?;
645+
self.interpret(pc, stack, control, func_bases, ctrl_bases)?;
646+
}
647+
RuntimeFunction::ImportedWasm { owner, function_index, .. } => {
648+
if let Some(owner_rc) = owner.upgrade() {
649+
owner_rc.call_function_idx(*function_index, return_pc, stack, control, func_bases, ctrl_bases)?;
660650
} else {
661-
let pc = Self::setup_wasm_function_call(*runtime_sig, *pc_start, *locals_count, stack, control, func_bases, ctrl_bases, *return_pc)?;
662-
self.interpret(pc, stack, control, func_bases, ctrl_bases)?;
651+
return Err(Error::Trap(FUNC_NO_IMPL));
663652
}
664653
}
665654
RuntimeFunction::Host { callback, runtime_sig } => {
@@ -893,7 +882,7 @@ impl Instance {
893882
let offset: u32 = read_leb128(bytes, &mut pc)?;
894883
let addr = pop_val!().as_u32();
895884
let mem = mem_opt.ok_or_else(|| Error::Validation(UNKNOWN_MEMORY))?;
896-
let v = mem.borrow().$method(addr, offset).map_err(|e| Error::Trap(e))?;
885+
let v = mem.borrow().$method(addr, offset).map_err(Error::Trap)?;
897886
let val = ($push)(v);
898887
stack.push(val);
899888
}}}
@@ -904,7 +893,7 @@ impl Instance {
904893
let addr = pop_val!().as_u32();
905894
let val = ($from)(raw);
906895
let mem = mem_opt.ok_or_else(|| Error::Validation(UNKNOWN_MEMORY))?;
907-
mem.borrow_mut().$method(addr, offset, val).map_err(|e| Error::Trap(e))?;
896+
mem.borrow_mut().$method(addr, offset, val).map_err(Error::Trap)?;
908897
}}}
909898

910899
loop {
@@ -1017,25 +1006,24 @@ impl Instance {
10171006
let f = &self.functions[fi as usize];
10181007

10191008
match f {
1020-
RuntimeFunction::Wasm { runtime_sig, pc_start, locals_count, owner, function_index: owner_idx } => {
1021-
if let (Some(owner_weak), Some(idx)) = (owner, owner_idx) {
1022-
if let Some(owner_rc) = owner_weak.upgrade() {
1023-
let n_params = runtime_sig.n_params() as usize;
1024-
let params_start = stack.len() - n_params;
1025-
let mut tmp_stack: Vec<WasmValue> = vec![WasmValue::default(); n_params];
1026-
tmp_stack[..n_params].copy_from_slice(&stack[params_start..(n_params + params_start)]);
1027-
stack.truncate(params_start);
1028-
let mut control_nested: Vec<ControlFrame> = Vec::new();
1029-
let mut ret_pc_nested = 0usize;
1030-
let mut func_bases_nested: Vec<usize> = Vec::new();
1031-
let mut ctrl_bases_nested = vec![];
1032-
owner_rc.call_function_idx(*idx, &mut ret_pc_nested, &mut tmp_stack, &mut control_nested, &mut func_bases_nested, &mut ctrl_bases_nested)?;
1033-
for v in tmp_stack { stack.push(v); }
1034-
} else {
1035-
return Err(Error::Trap(FUNC_NO_IMPL));
1036-
}
1009+
RuntimeFunction::OwnedWasm { runtime_sig, pc_start, locals_count } => {
1010+
pc = Self::setup_wasm_function_call(*runtime_sig, *pc_start, *locals_count, stack, control, func_bases, ctrl_bases, pc)?;
1011+
}
1012+
RuntimeFunction::ImportedWasm { owner, function_index, runtime_sig } => {
1013+
if let Some(owner_rc) = owner.upgrade() {
1014+
let n_params = runtime_sig.n_params() as usize;
1015+
let params_start = stack.len() - n_params;
1016+
let mut tmp_stack: Vec<WasmValue> = Vec::with_capacity(n_params);
1017+
tmp_stack.extend_from_slice(&stack[params_start..(n_params + params_start)]);
1018+
stack.truncate(params_start);
1019+
let mut control_nested: Vec<ControlFrame> = Vec::new();
1020+
let mut ret_pc_nested = 0usize;
1021+
let mut func_bases_nested: Vec<usize> = Vec::new();
1022+
let mut ctrl_bases_nested = vec![];
1023+
owner_rc.call_function_idx(*function_index, &mut ret_pc_nested, &mut tmp_stack, &mut control_nested, &mut func_bases_nested, &mut ctrl_bases_nested)?;
1024+
for v in tmp_stack { stack.push(v); }
10371025
} else {
1038-
pc = Self::setup_wasm_function_call(*runtime_sig, *pc_start, *locals_count, stack, control, func_bases, ctrl_bases, pc)?;
1026+
return Err(Error::Trap(FUNC_NO_IMPL));
10391027
}
10401028
}
10411029
RuntimeFunction::Host { callback, runtime_sig } => {
@@ -1094,7 +1082,7 @@ impl Instance {
10941082
let n_params = callee.param_count();
10951083
let params_start = stack.len() - n_params;
10961084
let mut tmp_stack: Vec<WasmValue> = Vec::with_capacity(n_params);
1097-
for i in 0..n_params { tmp_stack.push(stack[params_start + i]); }
1085+
tmp_stack.extend_from_slice(&stack[params_start..(params_start + n_params)]);
10981086
stack.truncate(params_start);
10991087
let mut control_nested: Vec<ControlFrame> = Vec::new();
11001088
let mut ret_pc_nested = 0usize;
@@ -1126,27 +1114,26 @@ impl Instance {
11261114
}
11271115

11281116
match callee {
1129-
RuntimeFunction::Wasm { runtime_sig, pc_start, locals_count, owner, function_index: owner_idx } => {
1130-
if let (Some(owner_weak), Some(idx)) = (&owner, owner_idx) {
1131-
if let Some(owner_rc) = owner_weak.upgrade() {
1132-
let n_params = runtime_sig.n_params() as usize;
1133-
let params_start = stack.len() - n_params;
1134-
let mut tmp_stack: Vec<WasmValue> = Vec::with_capacity(n_params);
1135-
for i in 0..n_params { tmp_stack.push(stack[params_start + i]); }
1136-
stack.truncate(params_start);
1137-
let mut control_nested: Vec<ControlFrame> = Vec::new();
1138-
let mut ret_pc_nested = 0usize;
1139-
let mut func_bases_nested: Vec<usize> = Vec::new();
1140-
let mut ctrl_bases_nested = vec![];
1141-
owner_rc.call_function_idx(idx, &mut ret_pc_nested, &mut tmp_stack, &mut control_nested, &mut func_bases_nested, &mut ctrl_bases_nested)?;
1142-
for v in tmp_stack { stack.push(v); }
1143-
} else {
1144-
return Err(Error::Trap(FUNC_NO_IMPL));
1145-
}
1117+
RuntimeFunction::ImportedWasm { runtime_sig, owner, function_index } => {
1118+
if let Some(owner_rc) = owner.upgrade() {
1119+
let n_params = runtime_sig.n_params() as usize;
1120+
let params_start = stack.len() - n_params;
1121+
let mut tmp_stack: Vec<WasmValue> = Vec::with_capacity(n_params);
1122+
tmp_stack.extend_from_slice(&stack[params_start..(params_start + n_params)]);
1123+
stack.truncate(params_start);
1124+
let mut control_nested: Vec<ControlFrame> = Vec::new();
1125+
let mut ret_pc_nested = 0usize;
1126+
let mut func_bases_nested: Vec<usize> = Vec::new();
1127+
let mut ctrl_bases_nested = vec![];
1128+
owner_rc.call_function_idx(function_index, &mut ret_pc_nested, &mut tmp_stack, &mut control_nested, &mut func_bases_nested, &mut ctrl_bases_nested)?;
1129+
for v in tmp_stack { stack.push(v); }
11461130
} else {
1147-
pc = Self::setup_wasm_function_call(runtime_sig, pc_start, locals_count, stack, control, func_bases, ctrl_bases, pc)?;
1131+
return Err(Error::Trap(FUNC_NO_IMPL));
11481132
}
11491133
}
1134+
RuntimeFunction::OwnedWasm { runtime_sig, pc_start, locals_count } => {
1135+
pc = Self::setup_wasm_function_call(runtime_sig, pc_start, locals_count, stack, control, func_bases, ctrl_bases, pc)?;
1136+
}
11501137
RuntimeFunction::Host { callback, runtime_sig } => {
11511138
let param_count = runtime_sig.n_params() as usize;
11521139
let params_start = stack.len() - param_count;
@@ -1456,26 +1443,23 @@ impl Instance {
14561443
let return_pc: usize = 0;
14571444

14581445
match func {
1459-
RuntimeFunction::Wasm { runtime_sig, pc_start, locals_count, owner, function_index: owner_idx } => {
1460-
// Execute in the correct instance: if this Function has an owner,
1461-
// delegate invocation to that instance.
1462-
if let (Some(owner_weak), Some(idx)) = (owner, owner_idx) {
1463-
if let Some(owner_rc) = owner_weak.upgrade() {
1464-
let mut owned_stack = Vec::with_capacity(64);
1465-
owned_stack.extend_from_slice(args);
1466-
let mut control: Vec<ControlFrame> = Vec::new();
1467-
let mut return_pc: usize = 0;
1468-
let mut func_bases: Vec<usize> = Vec::new();
1469-
let mut ctrl_bases = vec![];
1470-
owner_rc.call_function_idx(*idx, &mut return_pc, &mut owned_stack, &mut control, &mut func_bases, &mut ctrl_bases)?;
1471-
return Ok(owned_stack);
1472-
} else {
1473-
return Err(Error::Trap(FUNC_NO_IMPL));
1474-
}
1446+
RuntimeFunction::OwnedWasm { runtime_sig, pc_start, locals_count } => {
1447+
let mut ctrl_bases = Vec::new();
1448+
let pc = Self::setup_wasm_function_call(*runtime_sig, *pc_start, *locals_count, &mut stack, &mut control, &mut func_bases, &mut ctrl_bases, return_pc)?;
1449+
self.interpret(pc, &mut stack, &mut control, &mut func_bases, &mut ctrl_bases)?;
1450+
}
1451+
RuntimeFunction::ImportedWasm { owner, function_index, .. } => {
1452+
if let Some(owner_rc) = owner.upgrade() {
1453+
let mut owned_stack = Vec::with_capacity(64);
1454+
owned_stack.extend_from_slice(args);
1455+
let mut control: Vec<ControlFrame> = Vec::new();
1456+
let mut return_pc: usize = 0;
1457+
let mut func_bases: Vec<usize> = Vec::new();
1458+
let mut ctrl_bases = vec![];
1459+
owner_rc.call_function_idx(*function_index, &mut return_pc, &mut owned_stack, &mut control, &mut func_bases, &mut ctrl_bases)?;
1460+
return Ok(owned_stack);
14751461
} else {
1476-
let mut ctrl_bases = Vec::new();
1477-
let pc = Self::setup_wasm_function_call(*runtime_sig, *pc_start, *locals_count, &mut stack, &mut control, &mut func_bases, &mut ctrl_bases, return_pc)?;
1478-
self.interpret(pc, &mut stack, &mut control, &mut func_bases, &mut ctrl_bases)?;
1462+
return Err(Error::Trap(FUNC_NO_IMPL));
14791463
}
14801464
}
14811465
RuntimeFunction::Host { callback, .. } => {

src/wasm_memory.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,12 @@ impl WasmMemory {
7676
pub fn store_f64(&mut self, ptr: u32, offset: u32, v: f64) -> Result<(), &'static str> {
7777
self.store_u64(ptr, offset, v.to_bits())
7878
}
79+
#[inline]
80+
pub fn write_bytes(&mut self, offset: u32, bytes: &[u8]) -> Result<(), &'static str> {
81+
let start = offset as usize;
82+
let end = start.checked_add(bytes.len()).ok_or(OOB_MEMORY_ACCESS)?;
83+
if end > self.data.len() { return Err(OOB_MEMORY_ACCESS); }
84+
self.data[start..end].copy_from_slice(bytes);
85+
Ok(())
86+
}
7987
}

tests/spec_tests.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,13 @@ fn externalized_exports_for(inst: &Rc<Instance>) -> HashMap<String, ExportValue>
8585
RuntimeFunction::Host { .. } => {
8686
out.insert(name.clone(), ExportValue::Function(src));
8787
}
88-
RuntimeFunction::Wasm { runtime_sig: ty, .. } => {
88+
RuntimeFunction::OwnedWasm { runtime_sig: ty, .. } | RuntimeFunction::ImportedWasm { runtime_sig: ty, .. } => {
8989
// For wasm-backed exports, expose an owner handle that
9090
// delegates execution into the owning instance
91-
out.insert(name.clone(), ExportValue::Function(RuntimeFunction::Wasm {
91+
out.insert(name.clone(), ExportValue::Function(RuntimeFunction::ImportedWasm {
9292
runtime_sig: ty,
93-
pc_start: 0, // Not used for cross-instance calls
94-
locals_count: 0,
95-
owner: Some(weak.clone()),
96-
function_index: Some(fi),
93+
owner: weak.clone(),
94+
function_index: fi,
9795
}));
9896
}
9997
}

0 commit comments

Comments
 (0)