Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f26a0ca

Browse files
feat: improve memory perf + basic bulk memory access
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 6b7596e commit f26a0ca

File tree

13 files changed

+396
-148
lines changed

13 files changed

+396
-148
lines changed

crates/parser/src/conversion.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,12 @@ pub fn process_operators<'a>(
332332
GlobalSet { global_index } => Instruction::GlobalSet(global_index),
333333
MemorySize { mem, mem_byte } => Instruction::MemorySize(mem, mem_byte),
334334
MemoryGrow { mem, mem_byte } => Instruction::MemoryGrow(mem, mem_byte),
335+
336+
MemoryCopy { dst_mem, src_mem } => Instruction::MemoryCopy(src_mem, dst_mem),
337+
MemoryFill { mem } => Instruction::MemoryFill(mem),
338+
MemoryInit { data_index, mem } => Instruction::MemoryInit(data_index, mem),
339+
DataDrop { data_index } => Instruction::DataDrop(data_index),
340+
335341
I32Const { value } => Instruction::I32Const(value),
336342
I64Const { value } => Instruction::I64Const(value),
337343
F32Const { value } => Instruction::F32Const(f32::from_bits(value.bits())),

crates/tinywasm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ default=["std", "parser", "logging"]
3333
logging=["log", "tinywasm-types/logging", "tinywasm-parser?/logging"]
3434
std=["tinywasm-parser?/std", "tinywasm-types/std"]
3535
parser=["tinywasm-parser"]
36+
unsafe=[]
3637

3738
[[test]]
3839
name="generate-charts"

crates/tinywasm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#![no_std]
2-
#![forbid(unsafe_code)]
32
#![doc(test(
43
no_crate_inject,
54
attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables))
65
))]
76
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)]
87
#![cfg_attr(nightly, feature(error_in_core))]
8+
#![cfg_attr(not(feature = "unsafe"), deny(unsafe_code))]
99

1010
//! A tiny WebAssembly Runtime written in Rust
1111
//!

crates/tinywasm/src/runtime/interpreter/macros.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,29 @@ macro_rules! mem_load {
1414
// TODO: there could be a lot of performance improvements here
1515
let mem_idx = $module.resolve_mem_addr($arg.mem_addr);
1616
let mem = $store.get_mem(mem_idx as usize)?;
17+
let mem_ref = mem.borrow_mut();
1718

1819
let addr = $stack.values.pop()?.raw_value();
19-
2020
let addr = $arg.offset.checked_add(addr).ok_or_else(|| {
2121
Error::Trap(crate::Trap::MemoryOutOfBounds {
2222
offset: $arg.offset as usize,
2323
len: core::mem::size_of::<$load_type>(),
24-
max: mem.borrow().max_pages(),
24+
max: mem_ref.max_pages(),
2525
})
2626
})?;
2727

2828
let addr: usize = addr.try_into().ok().ok_or_else(|| {
2929
Error::Trap(crate::Trap::MemoryOutOfBounds {
3030
offset: $arg.offset as usize,
3131
len: core::mem::size_of::<$load_type>(),
32-
max: mem.borrow().max_pages(),
32+
max: mem_ref.max_pages(),
3333
})
3434
})?;
3535

36-
let val: [u8; core::mem::size_of::<$load_type>()] = {
37-
let mem = mem.borrow_mut();
38-
let val = mem.load(addr, $arg.align as usize, core::mem::size_of::<$load_type>())?;
39-
val.try_into().expect("slice with incorrect length")
40-
};
41-
42-
let loaded_value = <$load_type>::from_le_bytes(val);
43-
$stack.values.push((loaded_value as $target_type).into());
36+
const LEN: usize = core::mem::size_of::<$load_type>();
37+
let val = mem_ref.load_as::<LEN, $load_type>(addr, $arg.align as usize)?;
38+
// let loaded_value = mem_ref.load_as::<$load_type>(addr, $arg.align as usize)?;
39+
$stack.values.push((val as $target_type).into());
4440
}};
4541
}
4642

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

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use macros::*;
2323
use traits::*;
2424

2525
impl InterpreterRuntime {
26-
#[inline(always)] // a small 2-3% performance improvement in some cases
26+
// #[inline(always)] // a small 2-3% performance improvement in some cases
2727
pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack) -> Result<()> {
2828
// The current call frame, gets updated inside of exec_one
2929
let mut cf = stack.call_stack.pop()?;
@@ -388,6 +388,42 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
388388
}
389389
}
390390

391+
// Bulk memory operations
392+
MemoryCopy(from, to) => {
393+
let size = stack.values.pop_t::<i32>()?;
394+
let src = stack.values.pop_t::<i32>()?;
395+
let dst = stack.values.pop_t::<i32>()?;
396+
397+
let mem = store.get_mem(module.resolve_mem_addr(*from) as usize)?;
398+
let mut mem = mem.borrow_mut();
399+
400+
if from == to {
401+
// copy within the same memory
402+
mem.copy_within(dst as usize, src as usize, size as usize)?;
403+
} else {
404+
// copy between two memories
405+
let mem2 = store.get_mem(module.resolve_mem_addr(*to) as usize)?;
406+
let mut mem2 = mem2.borrow_mut();
407+
mem2.copy_from_slice(dst as usize, mem.load(src as usize, 0, size as usize)?)?;
408+
}
409+
}
410+
411+
MemoryFill(addr) => {
412+
let size = stack.values.pop_t::<i32>()?;
413+
let val = stack.values.pop_t::<i32>()?;
414+
let dst = stack.values.pop_t::<i32>()?;
415+
416+
let mem = store.get_mem(module.resolve_mem_addr(*addr) as usize)?;
417+
let mut mem = mem.borrow_mut();
418+
mem.fill(dst as usize, size as usize, val as u8)?;
419+
}
420+
421+
// MemoryInit(data_index, mem_index) => {}
422+
// DataDrop(data_index) => {
423+
// // let data_idx = module.resolve_data_addr(*data_index);
424+
// // let data = store.get_data(data_idx as usize)?;
425+
// // data.borrow_mut().drop()?;
426+
// }
391427
I32Store(arg) => mem_store!(i32, arg, stack, store, module),
392428
I64Store(arg) => mem_store!(i64, arg, stack, store, module),
393429
F32Store(arg) => mem_store!(f32, arg, stack, store, module),

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ pub(crate) struct CallFrame {
5858
}
5959

6060
impl CallFrame {
61-
// TOOD: perf: this is called a lot, and it's a bit slow
6261
/// Push a new label to the label stack and ensure the stack has the correct values
6362
pub(crate) fn enter_label(&mut self, label_frame: LabelFrame, stack: &mut super::ValueStack) {
6463
if label_frame.params > 0 {
@@ -77,14 +76,14 @@ impl CallFrame {
7776
// will increment it by 1 since we're changing the "current" instr_ptr
7877
match break_to.ty {
7978
BlockType::Loop => {
79+
// this is a loop, so we want to jump back to the start of the loop
8080
self.instr_ptr = break_to.instr_ptr;
8181

82+
// We also want to push the params to the stack
83+
value_stack.break_to(break_to.stack_ptr, break_to.params);
84+
8285
// check if we're breaking to the loop
8386
if break_to_relative != 0 {
84-
// this is a loop, so we want to jump back to the start of the loop
85-
// We also want to push the params to the stack
86-
value_stack.break_to(break_to.stack_ptr, break_to.params);
87-
8887
// we also want to trim the label stack to the loop (but not including the loop)
8988
self.labels.truncate(self.labels.len() - break_to_relative as usize);
9089
return Some(());

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use core::ops::Range;
22

33
use crate::{cold, runtime::RawWasmValue, unlikely, Error, Result};
4-
use alloc::vec;
54
use alloc::vec::Vec;
65
use tinywasm_types::{ValType, WasmValue};
76

@@ -15,7 +14,7 @@ pub(crate) struct ValueStack {
1514

1615
impl Default for ValueStack {
1716
fn default() -> Self {
18-
Self { stack: vec![RawWasmValue::default(); MIN_VALUE_STACK_SIZE] }
17+
Self { stack: Vec::with_capacity(MIN_VALUE_STACK_SIZE) }
1918
}
2019
}
2120

crates/tinywasm/src/runtime/value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ impl Debug for RawWasmValue {
1818
}
1919

2020
impl RawWasmValue {
21+
#[inline(always)]
2122
pub fn raw_value(&self) -> u64 {
2223
self.0
2324
}

0 commit comments

Comments
 (0)