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

Skip to content

Commit f865161

Browse files
feat: pre-processed wasm
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 4c9385d commit f865161

File tree

21 files changed

+588
-373
lines changed

21 files changed

+588
-373
lines changed

ARCHITECTURE.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ Some key differences are:
1717
## Bytecode Format
1818

1919
To improve performance and reduce code size, instructions are encoded as enum variants instead of opcodes.
20-
This allows preprocessing the bytecode into a more compact format, which can be loaded directly into memory and executed without decoding later. This can skip the decoding step entirely on resource-constrained devices where memory is limited.
20+
This allows preprocessing the bytecode into a more compact format, which can be loaded directly into memory and executed without decoding later. This can skip the decoding step entirely on resource-constrained devices where memory is limited. See this [blog post](https://wasmer.io/posts/improving-with-zero-copy-deserialization) by Wasmer
21+
for more details which inspired this design.
2122

2223
Some instructions are split into multiple variants to reduce the size of the enum (e.g. `br_table` and `br_label`).
2324
Additionally, label instructions contain offsets relative to the current instruction to make branching faster and easier to implement.

Cargo.lock

Lines changed: 27 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benches/fibonacci.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn run_tinywasm(module: TinyWasmModule, iterations: i32) {
99
let mut store = Store::default();
1010
let imports = Imports::default();
1111
let instance = ModuleInstance::instantiate(&mut store, module, Some(imports)).expect("instantiate");
12-
let hello = instance.exported_func::<i32, i32>(&mut store, "fibonacci").expect("exported_func");
12+
let hello = instance.exported_func::<i32, i32>(&store, "fibonacci").expect("exported_func");
1313
hello.call(&mut store, iterations).expect("call");
1414
}
1515

@@ -29,8 +29,8 @@ fn criterion_benchmark(c: &mut Criterion) {
2929
let module = tinywasm_module(FIBONACCI);
3030

3131
let mut group = c.benchmark_group("fibonacci");
32-
group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(module.clone(), black_box(50))));
33-
group.bench_function("wasmi", |b| b.iter(|| run_wasmi(black_box(50))));
32+
group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(module.clone(), black_box(60))));
33+
group.bench_function("wasmi", |b| b.iter(|| run_wasmi(black_box(60))));
3434
}
3535

3636
criterion_group!(

benches/selfhosted.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn run_tinywasm(module: TinyWasmModule) {
1010
let mut imports = Imports::default();
1111
imports.define("env", "printi32", Extern::typed_func(|_: FuncContext<'_>, _: i32| Ok(()))).expect("define");
1212
let instance = ModuleInstance::instantiate(&mut store, module, Some(imports)).expect("instantiate");
13-
let hello = instance.exported_func::<(), ()>(&mut store, "hello").expect("exported_func");
13+
let hello = instance.exported_func::<(), ()>(&store, "hello").expect("exported_func");
1414
hello.call(&mut store, ()).expect("call");
1515
}
1616

@@ -32,7 +32,7 @@ fn criterion_benchmark(c: &mut Criterion) {
3232

3333
let mut group = c.benchmark_group("selfhosted");
3434
group.bench_function("tinywasm", |b| b.iter(|| run_tinywasm(module.clone())));
35-
group.bench_function("wasmi", |b| b.iter(|| run_wasmi()));
35+
group.bench_function("wasmi", |b| b.iter(run_wasmi));
3636
}
3737

3838
criterion_group!(

crates/parser/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ repository.workspace=true
1111
# fork of wasmparser with no_std support, see https://github.com/bytecodealliance/wasmtime/issues/3495
1212
wasmparser={version="0.100", package="wasmparser-nostd", default-features=false}
1313
log={version="0.4", optional=true}
14-
tinywasm-types={version="0.3.0-alpha.0", path="../types"}
14+
tinywasm-types={version="0.3.0-alpha.0", path="../types", default-features=false}
1515

1616
[features]
1717
default=["std", "logging"]
1818
logging=["log"]
19-
std=[]
19+
std=["tinywasm-types/std"]

crates/parser/src/lib.rs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ mod module;
2525
use alloc::{string::ToString, vec::Vec};
2626
pub use error::*;
2727
use module::ModuleReader;
28-
use tinywasm_types::WasmFunction;
28+
use tinywasm_types::{TypedWasmFunction, WasmFunction};
2929
use wasmparser::Validator;
3030

3131
pub use tinywasm_types::TinyWasmModule;
@@ -116,19 +116,13 @@ impl TryFrom<ModuleReader> for TinyWasmModule {
116116
.code
117117
.into_iter()
118118
.zip(code_type_addrs)
119-
.map(|(f, ty_idx)| {
120-
(
121-
ty_idx,
122-
WasmFunction {
123-
instructions: f.body,
124-
locals: f.locals,
125-
ty: reader
126-
.func_types
127-
.get(ty_idx as usize)
128-
.expect("No func type for func, this is a bug")
129-
.clone(),
130-
},
131-
)
119+
.map(|(f, ty_idx)| TypedWasmFunction {
120+
type_addr: ty_idx,
121+
wasm_function: WasmFunction {
122+
instructions: f.body,
123+
locals: f.locals,
124+
ty: reader.func_types.get(ty_idx as usize).expect("No func type for func, this is a bug").clone(),
125+
},
132126
})
133127
.collect::<Vec<_>>();
134128

crates/tinywasm/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ plotters={version="0.3"}
2929
pretty_env_logger="0.5"
3030

3131
[features]
32-
default=["std", "parser", "logging"]
32+
default=["std", "parser", "logging", "archive"]
3333
logging=["log", "tinywasm-types/logging", "tinywasm-parser?/logging"]
3434
std=["tinywasm-parser?/std", "tinywasm-types/std"]
3535
parser=["tinywasm-parser"]
36-
unsafe=[]
36+
unsafe=["tinywasm-types/unsafe"]
37+
archive=["tinywasm-types/archive"]
3738

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

crates/tinywasm/src/store/data.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use alloc::vec::Vec;
2+
use tinywasm_types::*;
3+
4+
/// A WebAssembly Data Instance
5+
///
6+
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#data-instances>
7+
#[derive(Debug)]
8+
pub(crate) struct DataInstance {
9+
pub(crate) data: Option<Vec<u8>>,
10+
pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances
11+
}
12+
13+
impl DataInstance {
14+
pub(crate) fn new(data: Option<Vec<u8>>, owner: ModuleInstanceAddr) -> Self {
15+
Self { data, _owner: owner }
16+
}
17+
18+
pub(crate) fn drop(&mut self) -> Option<()> {
19+
match self.data {
20+
None => None,
21+
Some(_) => {
22+
let _ = self.data.take();
23+
Some(())
24+
}
25+
}
26+
}
27+
}

crates/tinywasm/src/store/element.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use crate::TableElement;
2+
use alloc::vec::Vec;
3+
use tinywasm_types::*;
4+
5+
/// A WebAssembly Element Instance
6+
///
7+
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#element-instances>
8+
#[derive(Debug)]
9+
pub(crate) struct ElementInstance {
10+
pub(crate) kind: ElementKind,
11+
pub(crate) items: Option<Vec<TableElement>>, // none is the element was dropped
12+
_owner: ModuleInstanceAddr, // index into store.module_instances
13+
}
14+
15+
impl ElementInstance {
16+
pub(crate) fn new(kind: ElementKind, owner: ModuleInstanceAddr, items: Option<Vec<TableElement>>) -> Self {
17+
Self { kind, _owner: owner, items }
18+
}
19+
}

crates/tinywasm/src/store/function.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use crate::Function;
2+
use tinywasm_types::*;
3+
4+
#[derive(Debug, Clone)]
5+
/// A WebAssembly Function Instance
6+
///
7+
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances>
8+
pub(crate) struct FunctionInstance {
9+
pub(crate) func: Function,
10+
pub(crate) owner: ModuleInstanceAddr, // index into store.module_instances, none for host functions
11+
}

crates/tinywasm/src/store/global.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use alloc::{format, string::ToString};
2+
use tinywasm_types::*;
3+
4+
use crate::{runtime::RawWasmValue, Error, Result};
5+
6+
/// A WebAssembly Global Instance
7+
///
8+
/// See <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances>
9+
#[derive(Debug)]
10+
pub(crate) struct GlobalInstance {
11+
pub(crate) value: RawWasmValue,
12+
pub(crate) ty: GlobalType,
13+
pub(crate) _owner: ModuleInstanceAddr, // index into store.module_instances
14+
}
15+
16+
impl GlobalInstance {
17+
pub(crate) fn new(ty: GlobalType, value: RawWasmValue, owner: ModuleInstanceAddr) -> Self {
18+
Self { ty, value, _owner: owner }
19+
}
20+
21+
pub(crate) fn get(&self) -> WasmValue {
22+
self.value.attach_type(self.ty.ty)
23+
}
24+
25+
pub(crate) fn set(&mut self, val: WasmValue) -> Result<()> {
26+
if val.val_type() != self.ty.ty {
27+
return Err(Error::Other(format!(
28+
"global type mismatch: expected {:?}, got {:?}",
29+
self.ty.ty,
30+
val.val_type()
31+
)));
32+
}
33+
if !self.ty.mutable {
34+
return Err(Error::Other("global is immutable".to_string()));
35+
}
36+
self.value = val.into();
37+
Ok(())
38+
}
39+
}

0 commit comments

Comments
 (0)