Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 83a768d

Browse files
reduce instruction enum size
Signed-off-by: Henry Gressmann <[email protected]>
1 parent e883003 commit 83a768d

File tree

9 files changed

+76
-69
lines changed

9 files changed

+76
-69
lines changed

crates/parser/src/conversion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ pub(crate) fn convert_valtype(valtype: &wasmparser::ValType) -> ValType {
226226
}
227227

228228
pub(crate) fn convert_memarg(memarg: wasmparser::MemArg) -> MemoryArg {
229-
MemoryArg { offset: memarg.offset, align: memarg.align, align_max: memarg.max_align, mem_addr: memarg.memory }
229+
MemoryArg { offset: memarg.offset, mem_addr: memarg.memory }
230230
}
231231

232232
pub(crate) fn process_const_operators(ops: OperatorsReader<'_>) -> Result<ConstInstruction> {

crates/parser/src/visit.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -338,15 +338,16 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
338338
}
339339

340340
fn visit_local_set(&mut self, idx: u32) -> Self::Output {
341-
if self.instructions.len() < 1 {
342-
return self.visit(Instruction::I64Rotl);
341+
if let Some(instruction) = self.instructions.last_mut() {
342+
match instruction {
343+
// Needs more testing, seems to make performance worse
344+
// Instruction::LocalGet(a) => *instruction = Instruction::LocalGetSet(*a, idx),
345+
_ => return self.visit(Instruction::LocalSet(idx)),
346+
};
347+
// Ok(())
348+
} else {
349+
self.visit(Instruction::LocalSet(idx))
343350
}
344-
345-
// LocalGetSet
346-
match self.instructions[self.instructions.len() - 1..] {
347-
// Instruction::LocalGet(a) => *instruction = Instruction::LocalGetSet(*a, idx),
348-
_ => return self.visit(Instruction::LocalSet(idx)),
349-
};
350351
}
351352

352353
fn visit_local_tee(&mut self, idx: u32) -> Self::Output {
@@ -413,7 +414,7 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
413414

414415
match self.instructions[label_pointer] {
415416
Instruction::Else(ref mut else_instr_end_offset) => {
416-
*else_instr_end_offset = current_instr_ptr - label_pointer;
417+
*else_instr_end_offset = (current_instr_ptr - label_pointer as usize) as u32;
417418

418419
#[cold]
419420
fn error() -> crate::ParseError {
@@ -430,13 +431,13 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
430431
return Err(error());
431432
};
432433

433-
*else_offset = Some(label_pointer - if_label_pointer);
434-
*end_offset = current_instr_ptr - if_label_pointer;
434+
*else_offset = Some((label_pointer - if_label_pointer) as u32);
435+
*end_offset = (current_instr_ptr - if_label_pointer) as u32;
435436
}
436437
Instruction::Block(_, ref mut end_offset)
437438
| Instruction::Loop(_, ref mut end_offset)
438439
| Instruction::If(_, _, ref mut end_offset) => {
439-
*end_offset = current_instr_ptr - label_pointer;
440+
*end_offset = (current_instr_ptr - label_pointer) as u32;
440441
}
441442
_ => {
442443
return Err(crate::ParseError::UnsupportedOperator(
@@ -456,7 +457,9 @@ impl<'a> wasmparser::VisitOperator<'a> for FunctionBuilder {
456457
.collect::<Result<Vec<Instruction>, wasmparser::BinaryReaderError>>()
457458
.expect("BrTable targets are invalid, this should have been caught by the validator");
458459

459-
self.instructions.extend(IntoIterator::into_iter([Instruction::BrTable(def, instrs.len())]).chain(instrs));
460+
self.instructions
461+
.extend(IntoIterator::into_iter([Instruction::BrTable(def, instrs.len() as u32)]).chain(instrs));
462+
460463
Ok(())
461464
}
462465

crates/tinywasm/src/reference.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,21 @@ pub struct MemoryRefMut<'a> {
2626
impl<'a> MemoryRefLoad for MemoryRef<'a> {
2727
/// Load a slice of memory
2828
fn load(&self, offset: usize, len: usize) -> Result<&[u8]> {
29-
self.instance.load(offset, 0, len)
29+
self.instance.load(offset, len)
3030
}
3131
}
3232

3333
impl<'a> MemoryRefLoad for MemoryRefMut<'a> {
3434
/// Load a slice of memory
3535
fn load(&self, offset: usize, len: usize) -> Result<&[u8]> {
36-
self.instance.load(offset, 0, len)
36+
self.instance.load(offset, len)
3737
}
3838
}
3939

4040
impl MemoryRef<'_> {
4141
/// Load a slice of memory
4242
pub fn load(&self, offset: usize, len: usize) -> Result<&[u8]> {
43-
self.instance.load(offset, 0, len)
43+
self.instance.load(offset, len)
4444
}
4545

4646
/// Load a slice of memory as a vector
@@ -52,7 +52,7 @@ impl MemoryRef<'_> {
5252
impl MemoryRefMut<'_> {
5353
/// Load a slice of memory
5454
pub fn load(&self, offset: usize, len: usize) -> Result<&[u8]> {
55-
self.instance.load(offset, 0, len)
55+
self.instance.load(offset, len)
5656
}
5757

5858
/// Load a slice of memory as a vector
@@ -82,7 +82,7 @@ impl MemoryRefMut<'_> {
8282

8383
/// Store a slice of memory
8484
pub fn store(&mut self, offset: usize, len: usize, data: &[u8]) -> Result<()> {
85-
self.instance.store(offset, 0, data, len)
85+
self.instance.store(offset, len, data)
8686
}
8787
}
8888

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ macro_rules! mem_load {
5252
})?;
5353

5454
const LEN: usize = core::mem::size_of::<$load_type>();
55-
let val = mem_ref.load_as::<LEN, $load_type>(addr, $arg.align as usize)?;
55+
let val = mem_ref.load_as::<LEN, $load_type>(addr)?;
5656
$stack.values.push((val as $target_type).into());
5757
}};
5858
}
@@ -76,7 +76,7 @@ macro_rules! mem_store {
7676
let val = val as $store_type;
7777
let val = val.to_le_bytes();
7878

79-
mem.borrow_mut().store(($arg.offset + addr) as usize, $arg.align as usize, &val, val.len())?;
79+
mem.borrow_mut().store(($arg.offset + addr) as usize, val.len(), &val)?;
8080
}};
8181
}
8282

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

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
202202
cf.enter_block(
203203
BlockFrame::new(
204204
cf.instr_ptr,
205-
cf.instr_ptr + end_offset,
205+
cf.instr_ptr + end_offset as usize,
206206
stack.values.len(),
207207
BlockType::If,
208208
&args,
@@ -217,25 +217,25 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
217217
// falsy value is on the top of the stack
218218
if let Some(else_offset) = else_offset {
219219
let label = BlockFrame::new(
220-
cf.instr_ptr + else_offset,
221-
cf.instr_ptr + end_offset,
220+
cf.instr_ptr + else_offset as usize,
221+
cf.instr_ptr + end_offset as usize,
222222
stack.values.len(),
223223
BlockType::Else,
224224
&args,
225225
module,
226226
);
227-
cf.instr_ptr += else_offset;
227+
cf.instr_ptr += else_offset as usize;
228228
cf.enter_block(label, &mut stack.values, &mut stack.blocks);
229229
} else {
230-
cf.instr_ptr += end_offset;
230+
cf.instr_ptr += end_offset as usize;
231231
}
232232
}
233233

234234
Loop(args, end_offset) => {
235235
cf.enter_block(
236236
BlockFrame::new(
237237
cf.instr_ptr,
238-
cf.instr_ptr + end_offset,
238+
cf.instr_ptr + end_offset as usize,
239239
stack.values.len(),
240240
BlockType::Loop,
241241
&args,
@@ -250,7 +250,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
250250
cf.enter_block(
251251
BlockFrame::new(
252252
cf.instr_ptr,
253-
cf.instr_ptr + end_offset,
253+
cf.instr_ptr + end_offset as usize,
254254
stack.values.len(), // - params,
255255
BlockType::Block,
256256
&args,
@@ -262,7 +262,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
262262
}
263263

264264
BrTable(default, len) => {
265-
let instr = cf.instructions()[cf.instr_ptr + 1..cf.instr_ptr + 1 + len]
265+
let instr = cf.instructions()[cf.instr_ptr + 1..cf.instr_ptr + 1 + len as usize]
266266
.iter()
267267
.map(|i| match i {
268268
BrLabel(l) => Ok(*l),
@@ -273,7 +273,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
273273
})
274274
.collect::<Result<Vec<_>>>()?;
275275

276-
if unlikely(instr.len() != len) {
276+
if unlikely(instr.len() != len as usize) {
277277
panic!(
278278
"Expected {} BrLabel instructions, got {}, this should have been validated by the parser",
279279
len,
@@ -319,7 +319,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
319319

320320
let res_count = block.results;
321321
stack.values.truncate_keep(block.stack_ptr, res_count);
322-
cf.instr_ptr += end_offset;
322+
cf.instr_ptr += end_offset as usize;
323323
}
324324

325325
EndBlockFrame => {
@@ -409,7 +409,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
409409
// copy between two memories
410410
let mem2 = store.get_mem(module.resolve_mem_addr(to) as usize)?;
411411
let mut mem2 = mem2.borrow_mut();
412-
mem2.copy_from_slice(dst as usize, mem.load(src as usize, 0, size as usize)?)?;
412+
mem2.copy_from_slice(dst as usize, mem.load(src as usize, size as usize)?)?;
413413
}
414414
}
415415

@@ -447,7 +447,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
447447
let data = &data[offset..(offset + size)];
448448

449449
// mem.store checks bounds
450-
mem.store(dst, 0, data, size)?;
450+
mem.store(dst, size, data)?;
451451
}
452452

453453
DataDrop(data_index) => {
@@ -704,6 +704,11 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
704704
stack.values.push(cf.get_local(b as usize));
705705
}
706706

707+
LocalGetSet(a, b) => {
708+
let a = cf.get_local(a as usize);
709+
cf.set_local(b as usize, a);
710+
}
711+
707712
// I64Xor + I64Const + I64RotL
708713
I64XorConstRotl(rotate_by) => {
709714
let val = stack.values.pop_t::<i64>()?;

crates/tinywasm/src/runtime/value.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use tinywasm_types::{ValType, WasmValue};
77
///
88
/// See [`WasmValue`] for the public representation.
99
#[derive(Clone, Copy, Default, PartialEq, Eq)]
10-
#[repr(transparent)]
1110
// pub struct RawWasmValue([u8; 16]);
1211
pub struct RawWasmValue([u8; 8]);
1312

crates/tinywasm/src/store/memory.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl MemoryInstance {
3737
Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len, max: self.data.len() })
3838
}
3939

40-
pub(crate) fn store(&mut self, addr: usize, _align: usize, data: &[u8], len: usize) -> Result<()> {
40+
pub(crate) fn store(&mut self, addr: usize, len: usize, data: &[u8]) -> Result<()> {
4141
let Some(end) = addr.checked_add(len) else {
4242
return Err(self.trap_oob(addr, data.len()));
4343
};
@@ -67,7 +67,7 @@ impl MemoryInstance {
6767
self.kind.page_count_max.unwrap_or(MAX_PAGES as u64) as usize
6868
}
6969

70-
pub(crate) fn load(&self, addr: usize, _align: usize, len: usize) -> Result<&[u8]> {
70+
pub(crate) fn load(&self, addr: usize, len: usize) -> Result<&[u8]> {
7171
let Some(end) = addr.checked_add(len) else {
7272
return Err(self.trap_oob(addr, len));
7373
};
@@ -80,7 +80,7 @@ impl MemoryInstance {
8080
}
8181

8282
// this is a workaround since we can't use generic const expressions yet (https://github.com/rust-lang/rust/issues/76560)
83-
pub(crate) fn load_as<const SIZE: usize, T: MemLoadable<SIZE>>(&self, addr: usize, _align: usize) -> Result<T> {
83+
pub(crate) fn load_as<const SIZE: usize, T: MemLoadable<SIZE>>(&self, addr: usize) -> Result<T> {
8484
let Some(end) = addr.checked_add(SIZE) else {
8585
return Err(self.trap_oob(addr, SIZE));
8686
};
@@ -223,16 +223,16 @@ mod memory_instance_tests {
223223
fn test_memory_store_and_load() {
224224
let mut memory = create_test_memory();
225225
let data_to_store = [1, 2, 3, 4];
226-
assert!(memory.store(0, 0, &data_to_store, data_to_store.len()).is_ok());
227-
let loaded_data = memory.load(0, 0, data_to_store.len()).unwrap();
226+
assert!(memory.store(0, data_to_store.len(), &data_to_store).is_ok());
227+
let loaded_data = memory.load(0, data_to_store.len()).unwrap();
228228
assert_eq!(loaded_data, &data_to_store);
229229
}
230230

231231
#[test]
232232
fn test_memory_store_out_of_bounds() {
233233
let mut memory = create_test_memory();
234234
let data_to_store = [1, 2, 3, 4];
235-
assert!(memory.store(memory.data.len(), 0, &data_to_store, data_to_store.len()).is_err());
235+
assert!(memory.store(memory.data.len(), data_to_store.len(), &data_to_store).is_err());
236236
}
237237

238238
#[test]

crates/tinywasm/src/store/mod.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -349,36 +349,36 @@ impl Store {
349349
let data_count = self.data.datas.len();
350350
let mut data_addrs = Vec::with_capacity(data_count);
351351
for (i, data) in datas.into_iter().enumerate() {
352-
let data_val =
353-
match data.kind {
354-
tinywasm_types::DataKind::Active { mem: mem_addr, offset } => {
355-
// a. Assert: memidx == 0
356-
if mem_addr != 0 {
357-
return Err(Error::UnsupportedFeature("data segments for non-zero memories".to_string()));
358-
}
352+
let data_val = match data.kind {
353+
tinywasm_types::DataKind::Active { mem: mem_addr, offset } => {
354+
// a. Assert: memidx == 0
355+
if mem_addr != 0 {
356+
return Err(Error::UnsupportedFeature("data segments for non-zero memories".to_string()));
357+
}
359358

360-
let mem_addr = mem_addrs.get(mem_addr as usize).copied().ok_or_else(|| {
361-
Error::Other(format!("memory {} not found for data segment {}", mem_addr, i))
362-
})?;
359+
let mem_addr = mem_addrs
360+
.get(mem_addr as usize)
361+
.copied()
362+
.ok_or_else(|| Error::Other(format!("memory {} not found for data segment {}", mem_addr, i)))?;
363363

364-
let offset = self.eval_i32_const(&offset)?;
364+
let offset = self.eval_i32_const(&offset)?;
365365

366-
let mem = self.data.memories.get_mut(mem_addr as usize).ok_or_else(|| {
366+
let mem =
367+
self.data.memories.get_mut(mem_addr as usize).ok_or_else(|| {
367368
Error::Other(format!("memory {} not found for data segment {}", mem_addr, i))
368369
})?;
369370

370-
// See comment for active element sections in the function above why we need to do this here
371-
if let Err(Error::Trap(trap)) =
372-
mem.borrow_mut().store(offset as usize, 0, &data.data, data.data.len())
373-
{
374-
return Ok((data_addrs.into_boxed_slice(), Some(trap)));
375-
}
376-
377-
// drop the data
378-
None
371+
// See comment for active element sections in the function above why we need to do this here
372+
if let Err(Error::Trap(trap)) = mem.borrow_mut().store(offset as usize, data.data.len(), &data.data)
373+
{
374+
return Ok((data_addrs.into_boxed_slice(), Some(trap)));
379375
}
380-
tinywasm_types::DataKind::Passive => Some(data.data.to_vec()),
381-
};
376+
377+
// drop the data
378+
None
379+
}
380+
tinywasm_types::DataKind::Passive => Some(data.data.to_vec()),
381+
};
382382

383383
self.data.datas.push(DataInstance::new(data_val, idx));
384384
data_addrs.push((i + data_count) as Addr);

crates/types/src/instructions.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ pub enum BlockArgs {
1515
pub struct MemoryArg {
1616
pub offset: u64,
1717
pub mem_addr: MemAddr,
18-
pub align: u8,
19-
pub align_max: u8,
18+
// pub align: u8,
19+
// pub align_max: u8,
2020
}
2121

2222
type BrTableDefault = u32;
23-
type BrTableLen = usize;
24-
type EndOffset = usize;
25-
type ElseOffset = usize;
23+
type BrTableLen = u32;
24+
type EndOffset = u32;
25+
type ElseOffset = u32;
2626

2727
#[derive(Debug, Clone, Copy, PartialEq)]
2828
#[cfg_attr(feature = "archive", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize), archive(check_bytes))]
@@ -62,7 +62,7 @@ pub enum Instruction {
6262

6363
// LocalGet + I32Const + I32Store
6464
// Also common, helps us skip the stack entirely
65-
I32LocalGetConstStore(LocalAddr, i32, MemoryArg), // I32Store + LocalGet + I32Const
65+
// I32LocalGetConstStore(LocalAddr, i32, MemoryArg), // I32Store + LocalGet + I32Const
6666

6767
// I64Xor + I64Const + I64RotL
6868
// Commonly used by a few crypto libraries

0 commit comments

Comments
 (0)