Skip to content

Commit 6443957

Browse files
feat: compact value stack (#21)
Not fully done, but ready for the `next` branch now. This changes how values are represented internally, making this pr particularly large, as this touches most parts of the codebase. The parser should now also be ready for multithreaded compilation to speed this up a bit. --------- Signed-off-by: Henry Gressmann <[email protected]>
1 parent ba1f263 commit 6443957

File tree

28 files changed

+1302
-1234
lines changed

28 files changed

+1302
-1234
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [UNRELEASED]
9+
10+
### Changed
11+
12+
- Improved support for WebAssembly 2.0 features
13+
- Simplify and optimize the interpreter loop
14+
- Use a seperate stack and locals for 32, 64 and 128 bit values and references (#21)
15+
- Updated to latest wasmparser version
16+
817
## [0.7.0] - 2024-05-15
918

1019
**All Commits**: https://github.com/explodingcamera/tinywasm/compare/v0.6.0...v0.7.0

Cargo.lock

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

crates/cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ argh="0.1"
2020
color-eyre={version="0.6", default-features=false}
2121
log="0.4"
2222
pretty_env_logger="0.5"
23-
wast={version="211.0", optional=true}
23+
wast={version="212.0", optional=true}
2424

2525
[features]
2626
default=["wat"]

crates/parser/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ repository.workspace=true
99
rust-version.workspace=true
1010

1111
[dependencies]
12-
wasmparser={version="0.211", default-features=false, features=["validate"]}
12+
wasmparser={version="0.212", default-features=false, features=["validate"]}
1313
log={version="0.4", optional=true}
1414
tinywasm-types={version="0.7.0", path="../types", default-features=false}
1515

crates/parser/src/conversion.rs

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::Result;
22
use crate::{module::Code, visit::process_operators_and_validate};
33
use alloc::{boxed::Box, format, string::ToString, vec::Vec};
44
use tinywasm_types::*;
5-
use wasmparser::{FuncValidator, OperatorsReader, ValidatorResources};
5+
use wasmparser::{FuncValidator, FuncValidatorAllocations, OperatorsReader, ValidatorResources};
66

77
pub(crate) fn convert_module_elements<'a, T: IntoIterator<Item = wasmparser::Result<wasmparser::Element<'a>>>>(
88
elements: T,
@@ -168,27 +168,45 @@ pub(crate) fn convert_module_export(export: wasmparser::Export<'_>) -> Result<Ex
168168

169169
pub(crate) fn convert_module_code(
170170
func: wasmparser::FunctionBody<'_>,
171-
validator: &mut FuncValidator<ValidatorResources>,
172-
) -> Result<Code> {
171+
mut validator: FuncValidator<ValidatorResources>,
172+
) -> Result<(Code, FuncValidatorAllocations)> {
173173
let locals_reader = func.get_locals_reader()?;
174174
let count = locals_reader.get_count();
175175
let pos = locals_reader.original_position();
176176

177-
let locals = {
178-
let mut locals = Vec::new();
179-
locals.reserve_exact(count as usize);
180-
for (i, local) in locals_reader.into_iter().enumerate() {
181-
let local = local?;
182-
validator.define_locals(pos + i, local.0, local.1)?;
183-
for _ in 0..local.0 {
184-
locals.push(convert_valtype(&local.1));
177+
// maps a local's address to the index in the type's locals array
178+
let mut local_addr_map = Vec::with_capacity(count as usize);
179+
let mut local_counts = LocalCounts::default();
180+
181+
for (i, local) in locals_reader.into_iter().enumerate() {
182+
let local = local?;
183+
validator.define_locals(pos + i, local.0, local.1)?;
184+
}
185+
186+
for i in 0..validator.len_locals() {
187+
match validator.get_local_type(i) {
188+
Some(wasmparser::ValType::I32) | Some(wasmparser::ValType::F32) => {
189+
local_addr_map.push(local_counts.local_32);
190+
local_counts.local_32 += 1;
191+
}
192+
Some(wasmparser::ValType::I64) | Some(wasmparser::ValType::F64) => {
193+
local_addr_map.push(local_counts.local_64);
194+
local_counts.local_64 += 1;
185195
}
196+
Some(wasmparser::ValType::V128) => {
197+
local_addr_map.push(local_counts.local_128);
198+
local_counts.local_128 += 1;
199+
}
200+
Some(wasmparser::ValType::Ref(_)) => {
201+
local_addr_map.push(local_counts.local_ref);
202+
local_counts.local_ref += 1;
203+
}
204+
None => return Err(crate::ParseError::UnsupportedOperator("Unknown local type".to_string())),
186205
}
187-
locals.into_boxed_slice()
188-
};
206+
}
189207

190-
let body = process_operators_and_validate(validator, func)?;
191-
Ok((body, locals))
208+
let (body, allocations) = process_operators_and_validate(validator, func, local_addr_map)?;
209+
Ok(((body, local_counts), allocations))
192210
}
193211

194212
pub(crate) fn convert_module_type(ty: wasmparser::RecGroup) -> Result<FuncType> {

crates/parser/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl Parser {
6262
component_model: false,
6363
component_model_nested_names: false,
6464
component_model_values: false,
65+
component_model_more_flags: false,
6566
exceptions: false,
6667
extended_const: false,
6768
gc: false,

crates/parser/src/module.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use crate::{conversion, ParseError, Result};
33
use alloc::string::ToString;
44
use alloc::{boxed::Box, format, vec::Vec};
55
use tinywasm_types::{
6-
Data, Element, Export, FuncType, Global, Import, Instruction, MemoryType, TableType, TinyWasmModule, ValType,
6+
Data, Element, Export, FuncType, Global, Import, Instruction, LocalCounts, MemoryType, TableType, TinyWasmModule,
77
WasmFunction,
88
};
99
use wasmparser::{FuncValidatorAllocations, Payload, Validator};
1010

11-
pub(crate) type Code = (Box<[Instruction]>, Box<[ValType]>);
11+
pub(crate) type Code = (Box<[Instruction]>, LocalCounts);
1212

1313
#[derive(Default)]
1414
pub(crate) struct ModuleReader {
@@ -135,9 +135,10 @@ impl ModuleReader {
135135
CodeSectionEntry(function) => {
136136
debug!("Found code section entry");
137137
let v = validator.code_section_entry(&function)?;
138-
let mut func_validator = v.into_validator(self.func_validator_allocations.take().unwrap_or_default());
139-
self.code.push(conversion::convert_module_code(function, &mut func_validator)?);
140-
self.func_validator_allocations = Some(func_validator.into_allocations());
138+
let func_validator = v.into_validator(self.func_validator_allocations.take().unwrap_or_default());
139+
let (code, allocations) = conversion::convert_module_code(function, func_validator)?;
140+
self.code.push(code);
141+
self.func_validator_allocations = Some(allocations);
141142
}
142143
ImportSection(reader) => {
143144
if !self.imports.is_empty() {

0 commit comments

Comments
 (0)