Skip to content

Commit 17c5dc6

Browse files
chore: cleanup, tweak api
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 455344b commit 17c5dc6

11 files changed

Lines changed: 247 additions & 229 deletions

File tree

‎crates/parser/src/visit.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,12 @@ macro_rules! atomic_visitors {
527527
let address = self.metadata.memory_size(memarg.memory)?;
528528
self.mark_memory(memarg.memory);
529529
let memory = self.push128(Operand128::<tinywasm_types::MemoryOperand>::new(memarg.offset, memarg.memory))?;
530+
let is_64 = atomic_visitors!(@is64 [$($input),*] [$($output),*]);
531+
let arg = AtomicArg::new(memory, AtomicWidth::from_bytes($width), is_64, AtomicOp::$op);
530532
self.emit(
531533
&[$(atomic_visitors!(@size $input, address)),*],
532534
&[$(atomic_visitors!(@size $output, address)),*],
533-
Instruction::Atomic(AtomicArg::new(memory, AtomicWidth::from_bytes($width), atomic_visitors!(@is64 [$($input),*] [$($output),*]), AtomicOp::$op)),
535+
Instruction::Atomic(arg),
534536
)
535537
}
536538
};

‎crates/tinywasm/src/imports.rs‎

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -237,23 +237,24 @@ impl ResolvedImports {
237237

238238
fn compare_memory_types(
239239
import: &Import,
240-
expected: &MemoryType,
241240
actual: &MemoryType,
241+
expected: &MemoryType,
242242
real_size: usize,
243243
) -> Result<()> {
244244
Self::compare_types(import, &expected.arch(), &actual.arch())?;
245245
Self::compare_types(import, &expected.shared(), &actual.shared())?;
246246

247-
if actual.page_count_initial() > expected.page_count_initial() && actual.page_count_initial() > real_size as u64
248-
{
247+
if (real_size as u64) < expected.page_count_initial() {
249248
return Err(LinkingError::incompatible_import_type(import).into());
250249
}
251250

252251
if expected.page_size() != actual.page_size() {
253252
return Err(LinkingError::incompatible_import_type(import).into());
254253
}
255254

256-
if expected.page_count_max() > actual.page_count_max() {
255+
if let Some(max) = expected.page_count_max_declared()
256+
&& actual.page_count_max_declared().is_none_or(|actual_max| actual_max > max)
257+
{
257258
return Err(LinkingError::incompatible_import_type(import).into());
258259
}
259260

@@ -364,20 +365,8 @@ impl ResolvedImports {
364365
imports.tables.push(table_addr);
365366
}
366367
(ExternVal::Memory(memory_addr), ImportKind::Memory(ty)) => {
367-
#[cfg(feature = "std")]
368-
let (kind, pages) = if memory_addr & crate::store::SHARED_MEM_BIT != 0 {
369-
let memory =
370-
&store.state.shared_memories[(memory_addr & !crate::store::SHARED_MEM_BIT) as usize];
371-
(memory.ty(), memory.page_count())
372-
} else {
373-
let memory = store.state.get_mem(memory_addr);
374-
(memory.kind, memory.page_count)
375-
};
376-
#[cfg(not(feature = "std"))]
377-
let (kind, pages) = {
378-
let memory = store.state.get_mem(memory_addr);
379-
(memory.kind, memory.page_count)
380-
};
368+
let kind = store.state.memory_type(memory_addr);
369+
let (_, pages) = store.state.memory_size(memory_addr);
381370
Self::compare_memory_types(import, &kind, ty, pages)?;
382371
imports.memories.push(memory_addr);
383372
}

‎crates/tinywasm/src/instance.rs‎

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,9 @@ impl ModuleInstance {
215215
addrs.tags.extend(store.init_tags(&module.tags, &type_addrs));
216216
let limiter = store.engine.config().resource_limiter.clone();
217217
if !module.skip_local_memory_allocation {
218-
addrs
219-
.memories
220-
.extend(store.init_memories(&module.memory_types, |ty| MemoryInstance::new(ty, limiter.as_deref()))?);
218+
let memories =
219+
store.init_memories(&module.memory_types, |ty| MemoryInstance::new(ty, limiter.as_deref()))?;
220+
addrs.memories.extend(memories);
221221
}
222222

223223
store.init_globals(&mut addrs.globals, &module.globals, &addrs.funcs, &type_addrs)?;
@@ -316,35 +316,15 @@ impl ModuleInstance {
316316
/// ```
317317
pub fn exports(&self) -> impl Iterator<Item = (&str, ExternItem)> + '_ {
318318
self.0.exports.iter().map(move |export| {
319-
let item = match export.kind {
320-
ExternalKind::Func => ExternItem::Func(Function {
321-
item: StoreItem::new(self.0.store_id, self.resolve_func_addr(export.index)),
322-
module_id: self.id(),
323-
}),
324-
ExternalKind::Table => {
325-
ExternItem::Table(Table(StoreItem::new(self.0.store_id, self.resolve_table_addr(export.index))))
326-
}
327-
ExternalKind::Memory => {
328-
let addr = self.resolve_mem_addr(export.index);
329-
#[cfg(feature = "std")]
330-
if addr & SHARED_MEM_BIT != 0 {
331-
ExternItem::MemoryShared(
332-
self.shared_backing(addr).expect("exported shared memory has a backing"),
333-
)
334-
} else {
335-
ExternItem::Memory(Memory(StoreItem::new(self.0.store_id, addr)))
336-
}
337-
#[cfg(not(feature = "std"))]
338-
ExternItem::Memory(Memory(StoreItem::new(self.0.store_id, addr)))
339-
}
340-
ExternalKind::Global => {
341-
ExternItem::Global(Global(StoreItem::new(self.0.store_id, self.resolve_global_addr(export.index))))
342-
}
343-
ExternalKind::Tag => {
344-
ExternItem::Tag(Tag(StoreItem::new(self.0.store_id, self.resolve_tag_addr(export.index))))
345-
}
319+
let addr = match export.kind {
320+
ExternalKind::Func => self.resolve_func_addr(export.index),
321+
ExternalKind::Table => self.resolve_table_addr(export.index),
322+
ExternalKind::Memory => self.resolve_mem_addr(export.index),
323+
ExternalKind::Global => self.resolve_global_addr(export.index),
324+
ExternalKind::Tag => self.resolve_tag_addr(export.index),
346325
};
347-
326+
let value = ExternVal::new(export.kind, addr);
327+
let item = self.resolve_extern(value).expect("exported extern has a backing");
348328
(export.name.as_ref(), item)
349329
})
350330
}
@@ -388,7 +368,11 @@ impl ModuleInstance {
388368
/// # }
389369
/// ```
390370
pub fn extern_item(&self, name: &str) -> Result<ExternItem> {
391-
match self.require_export(name)? {
371+
self.resolve_extern(self.require_export(name)?)
372+
}
373+
374+
fn resolve_extern(&self, value: ExternVal) -> Result<ExternItem> {
375+
match value {
392376
ExternVal::Func(addr) => {
393377
Ok(ExternItem::Func(Function { item: StoreItem::new(self.0.store_id, addr), module_id: self.id() }))
394378
}

‎crates/tinywasm/src/interpreter/executor/mod.rs‎

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -866,18 +866,17 @@ impl<'store> Executor<'store> {
866866
let value = T::local_get(&self.store.value_stack, &self.cf, u16::from(value_local));
867867
let mem_addr = self.mem_addr(MemAddr::from(memarg.memory()));
868868
crate::store::with_memory!(self.store.state, mem_addr, |mem, kind| {
869-
let addr = if kind.arch() == MemoryArch::I64 {
869+
let base = if kind.arch() == MemoryArch::I64 {
870870
let base = u64::local_get(&self.store.value_stack, &self.cf, u16::from(addr_local));
871-
let base = cold_err!(usize::try_from(base).map_err(|_| Trap::MemoryOutOfBounds {
871+
cold_err!(usize::try_from(base).map_err(|_| Trap::MemoryOutOfBounds {
872872
offset: usize::MAX,
873873
len: N,
874874
max: mem.len(),
875-
}))?;
876-
cold_err!(mem.effective_addr::<N>(base, u64::from(memarg.offset())))?
875+
}))?
877876
} else {
878-
let base = u32::local_get(&self.store.value_stack, &self.cf, u16::from(addr_local));
879-
cold_err!(mem.effective_addr::<N>(base as usize, u64::from(memarg.offset())))?
877+
u32::local_get(&self.store.value_stack, &self.cf, u16::from(addr_local)) as usize
880878
};
879+
let addr = cold_err!(mem.effective_addr::<N>(base, u64::from(memarg.offset())))?;
881880
value.store_at(&mut *mem, addr)
882881
})
883882
}
@@ -891,18 +890,17 @@ impl<'store> Executor<'store> {
891890
let memarg = index.resolve(&self.func.data);
892891
let mem_addr = self.mem_addr(MemAddr::from(memarg.memory()));
893892
crate::store::with_memory!(self.store.state, mem_addr, |mem, kind| {
894-
let addr = if kind.arch() == MemoryArch::I64 {
893+
let base = if kind.arch() == MemoryArch::I64 {
895894
let base = i64::local_get(&self.store.value_stack, &self.cf, u16::from(addr_local)) as u64;
896-
let base = cold_err!(usize::try_from(base).map_err(|_| Trap::MemoryOutOfBounds {
895+
cold_err!(usize::try_from(base).map_err(|_| Trap::MemoryOutOfBounds {
897896
offset: usize::MAX,
898897
len: N,
899898
max: mem.len(),
900-
}))?;
901-
cold_err!(mem.effective_addr::<N>(base, u64::from(memarg.offset())))?
899+
}))?
902900
} else {
903-
let base = u32::local_get(&self.store.value_stack, &self.cf, u16::from(addr_local));
904-
cold_err!(mem.effective_addr::<N>(base as usize, u64::from(memarg.offset())))?
901+
u32::local_get(&self.store.value_stack, &self.cf, u16::from(addr_local)) as usize
905902
};
903+
let addr = cold_err!(mem.effective_addr::<N>(base, u64::from(memarg.offset())))?;
906904

907905
let value = cold_err!(T::load_at(&*mem, addr))?;
908906
increment(value).store_at(&mut *mem, addr)
@@ -1343,28 +1341,19 @@ impl<'store> Executor<'store> {
13431341
let dst = self.store.value_stack.pop_memory_operand(arch)?;
13441342

13451343
let data = self.store.state.data[self.module.resolve_data_addr(data_index) as usize].data.clone();
1344+
// Dropped segments behave like empty segments, including valid zero-length copies.
1345+
let data = data.as_deref().unwrap_or_default();
1346+
let end = offset.checked_add(size).filter(|&end| end <= data.len()).ok_or(Trap::MemoryOutOfBounds {
1347+
offset,
1348+
len: size,
1349+
max: data.len(),
1350+
})?;
13461351
crate::store::with_memory!(self.store.state, mem_addr, |mem, kind| {
1347-
let data_len = data.as_ref().map_or(0, |d| d.len());
1348-
let mem_len = mem.len();
1349-
if offset.checked_add(size).is_none_or(|end| end > data_len) {
1350-
return cold!(Err(Trap::MemoryOutOfBounds { offset, len: size, max: data_len }));
1351-
}
1352-
if dst.checked_add(size).is_none_or(|end| end > mem_len) {
1353-
return cold!(Err(Trap::MemoryOutOfBounds { offset: dst, len: size, max: mem_len }));
1354-
}
1355-
1356-
if size == 0 {
1357-
return Ok(());
1358-
}
1359-
1360-
let Some(data) = &data else {
1361-
return cold!(Err(Trap::MemoryOutOfBounds { offset: 0, len: 0, max: 0 }));
1362-
};
1363-
1364-
if mem.write_all(dst, &data[offset..offset + size]).is_none() {
1365-
return cold!(Err(Trap::MemoryOutOfBounds { offset: dst, len: size, max: mem_len }));
1366-
}
1367-
Ok(())
1352+
cold_err!(mem.write_all(dst, &data[offset..end]).ok_or_else(|| Trap::MemoryOutOfBounds {
1353+
offset: dst,
1354+
len: size,
1355+
max: mem.len(),
1356+
}))
13681357
})
13691358
}
13701359

@@ -1531,10 +1520,9 @@ impl<'store> Executor<'store> {
15311520
}
15321521

15331522
match arg.is_64() {
1534-
true => u64::stack_push(&mut self.store.value_stack, old)?,
1535-
false => u32::stack_push(&mut self.store.value_stack, old as u32)?,
1523+
true => u64::stack_push(&mut self.store.value_stack, old),
1524+
false => u32::stack_push(&mut self.store.value_stack, old as u32),
15361525
}
1537-
Ok(())
15381526
})
15391527
}
15401528

@@ -1550,8 +1538,7 @@ impl<'store> Executor<'store> {
15501538
crate::store::with_memory!(self.store.state, mem_addr, |mem, kind| {
15511539
let base = self.store.value_stack.pop_memory_operand(kind.arch())?;
15521540
let addr = cold_err!(mem.effective_addr::<N>(base, m.offset()))?;
1553-
cold_err!(val.store_at(&mut *mem, addr))?;
1554-
Ok(())
1541+
cold_err!(val.store_at(&mut *mem, addr))
15551542
})
15561543
}
15571544

‎crates/tinywasm/src/store/memory/instance.rs‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@ impl core::fmt::Debug for MemoryInstance {
2323
}
2424

2525
impl MemoryInstance {
26+
/// Converts a page count to a byte length that fits the host address space.
2627
#[inline]
2728
pub(super) fn host_size(kind: MemoryType, pages: u64) -> Option<usize> {
2829
pages.checked_mul(kind.page_size()).and_then(|size| usize::try_from(size).ok())
2930
}
3031

32+
/// Returns the declared byte limit, saturating when it exceeds the host address space.
3133
#[inline]
32-
fn maximum_size(kind: MemoryType) -> Option<usize> {
34+
pub(super) fn maximum_size(kind: MemoryType) -> Option<usize> {
3335
kind.page_count_max_declared().map(|pages| Self::host_size(kind, pages).unwrap_or(usize::MAX))
3436
}
3537

38+
/// Applies the runtime's memory64 allocation cap to the declared page limit.
3639
#[inline]
3740
pub(super) fn page_count_max(kind: MemoryType) -> u64 {
3841
match kind.arch() {
@@ -101,6 +104,7 @@ impl MemoryInstance {
101104
Self::grow_storage(self.kind, &mut self.inner, &mut self.page_count, pages_delta, limiter)
102105
}
103106

107+
/// Grows exclusively borrowed storage after checking limits and the host limiter.
104108
pub(super) fn grow_storage(
105109
kind: MemoryType,
106110
inner: &mut MemoryStorage,

0 commit comments

Comments
 (0)