Skip to content

Commit 2f3238c

Browse files
use more peek stack access pattern
1 parent 80b5294 commit 2f3238c

3 files changed

Lines changed: 50 additions & 67 deletions

File tree

src/instance.rs

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -426,19 +426,19 @@ impl Instance {
426426
}
427427

428428
// Validate data segments (bounds check, defer writes)
429-
let mut pending_data: Vec<(u32, Vec<u8>)> = Vec::new();
429+
let mut pending_data: Vec<(u32, usize, usize)> = Vec::new();
430430
if let Some(mem) = &inst.memory {
431431
for seg in &module.data_segments {
432432
let mut ip = seg.initializer_offset;
433433
let offset = Instance::eval_const(&module, &mut ip, &inst.globals)?.as_u32();
434-
let bytes_vec = module.bytes[seg.data_range.clone()].to_vec();
434+
let data_len = seg.data_range.end - seg.data_range.start;
435435
let m = mem.borrow();
436-
let end = (offset as usize).saturating_add(bytes_vec.len());
436+
let end = (offset as usize).saturating_add(data_len);
437437
if end > (m.size() as usize) * (WasmMemory::PAGE_SIZE as usize) {
438438
return Err(Error::link(DATA_SEG_DNF));
439439
}
440440
drop(m);
441-
pending_data.push((offset, bytes_vec));
441+
pending_data.push((offset, seg.data_range.start, seg.data_range.end));
442442
}
443443
}
444444

@@ -466,8 +466,8 @@ impl Instance {
466466
// Apply data segments (writes), after elements
467467
if let Some(mem) = &inst.memory {
468468
let mut m = mem.borrow_mut();
469-
for (offset, bytes_vec) in &pending_data {
470-
m.write_bytes(*offset, bytes_vec).map_err(Error::trap)?;
469+
for &(offset, start, end) in &pending_data {
470+
m.write_bytes(offset, &module.bytes[start..end]).map_err(Error::trap)?;
471471
}
472472
}
473473

@@ -723,29 +723,25 @@ impl Instance {
723723
}
724724
macro_rules! shift {
725725
(u32, $op:tt) => {{
726-
let b = pop_val!().as_u32() % 32;
727-
let a = pop_val!().as_u32();
728-
stack.push(WasmValue::from_u32(a $op b));
726+
let (a, b) = peek_two!(u32);
727+
overwrite!(WasmValue::from_u32(a $op (b % 32)));
729728
}};
730729
(u64, $op:tt) => {{
731-
let b = pop_val!().as_u64() % 64;
732-
let a = pop_val!().as_u64();
733-
stack.push(WasmValue::from_u64(a $op b));
730+
let (a, b) = peek_two!(u64);
731+
overwrite!(WasmValue::from_u64(a $op (b % 64)));
734732
}};
735733
}
736734
macro_rules! rotate {
737735
(u32, $dir:ident) => {{
738-
let b = pop_val!().as_u32();
739-
let a = pop_val!().as_u32();
736+
let (a, b) = peek_two!(u32);
740737
paste! {
741-
stack.push(WasmValue::from_u32(a.[<rotate_ $dir>](b % 32)));
738+
overwrite!(WasmValue::from_u32(a.[<rotate_ $dir>](b % 32)));
742739
}
743740
}};
744741
(u64, $dir:ident) => {{
745-
let b = pop_val!().as_u64();
746-
let a = pop_val!().as_u64();
742+
let (a, b) = peek_two!(u64);
747743
paste! {
748-
stack.push(WasmValue::from_u64(a.[<rotate_ $dir>]((b % 64) as u32)));
744+
overwrite!(WasmValue::from_u64(a.[<rotate_ $dir>]((b % 64) as u32)));
749745
}
750746
}};
751747
}
@@ -762,8 +758,7 @@ impl Instance {
762758
($type:ident, max) => {{ minmax!(@impl $type, max, false) }};
763759
(@impl $type:ident, $op:ident, $want_negative:literal) => {{
764760
paste! {
765-
let b = pop_val!().[<as_ $type>]();
766-
let a = pop_val!().[<as_ $type>]();
761+
let (a, b) = peek_two!($type);
767762

768763
let result = if a.is_nan() {
769764
a
@@ -777,25 +772,23 @@ impl Instance {
777772
a.$op(b)
778773
};
779774

780-
stack.push(WasmValue::[<from_ $type>](result));
775+
overwrite!(WasmValue::[<from_ $type>](result));
781776
}
782777
}};
783778
}
784779
macro_rules! shr_s {
785780
($int_type:ident, $uint_type:ident, $bits:literal) => {{
786781
paste! {
787-
let b = pop_val!().[<as_ $uint_type>]() % $bits;
788-
let a = pop_val!().[<as_ $int_type>]();
789-
stack.push(WasmValue::[<from_ $int_type>](a >> b));
782+
let (a, b) = peek_two!($int_type);
783+
overwrite!(WasmValue::[<from_ $int_type>](a >> (b as $uint_type % $bits)));
790784
}
791785
}};
792786
}
793787
macro_rules! copysign {
794788
($type:ident) => {{
795789
paste! {
796-
let b = pop_val!().[<as_ $type>]();
797-
let a = pop_val!().[<as_ $type>]();
798-
stack.push(WasmValue::[<from_ $type>](a.copysign(b)));
790+
let (a, b) = peek_two!($type);
791+
overwrite!(WasmValue::[<from_ $type>](a.copysign(b)));
799792
}
800793
}};
801794
}
@@ -851,45 +844,38 @@ impl Instance {
851844
macro_rules! div_s {
852845
($int_type:ident) => {{
853846
paste! {
854-
let b = pop_val!().[<as_ $int_type>]();
855-
let a = pop_val!().[<as_ $int_type>]();
847+
let (a, b) = peek_two!($int_type);
856848
if b == 0 { return Err(Error::trap(DIVIDE_BY_ZERO)); }
857849
if a == $int_type::MIN && b == -1 { return Err(Error::trap(INTEGER_OVERFLOW)); }
858-
stack.push(WasmValue::[<from_ $int_type>](a / b));
850+
overwrite!(WasmValue::[<from_ $int_type>](a / b));
859851
}
860852
}};
861853
}
862854
macro_rules! div_u {
863855
($uint_type:ident) => {{
864856
paste! {
865-
let b = pop_val!().[<as_ $uint_type>]();
866-
let a = pop_val!().[<as_ $uint_type>]();
857+
let (a, b) = peek_two!($uint_type);
867858
if b == 0 { return Err(Error::trap(DIVIDE_BY_ZERO)); }
868-
stack.push(WasmValue::[<from_ $uint_type>](a / b));
859+
overwrite!(WasmValue::[<from_ $uint_type>](a / b));
869860
}
870861
}};
871862
}
872863
macro_rules! rem_s {
873864
($int_type:ident) => {{
874865
paste! {
875-
let b = pop_val!().[<as_ $int_type>]();
876-
let a = pop_val!().[<as_ $int_type>]();
866+
let (a, b) = peek_two!($int_type);
877867
if b == 0 { return Err(Error::trap(DIVIDE_BY_ZERO)); }
878-
if a == $int_type::MIN && b == -1 {
879-
stack.push(WasmValue::[<from_ $int_type>](0));
880-
} else {
881-
stack.push(WasmValue::[<from_ $int_type>](a % b));
882-
}
868+
let result = if a == $int_type::MIN && b == -1 { 0 } else { a % b };
869+
overwrite!(WasmValue::[<from_ $int_type>](result));
883870
}
884871
}};
885872
}
886873
macro_rules! rem_u {
887874
($uint_type:ident) => {{
888875
paste! {
889-
let b = pop_val!().[<as_ $uint_type>]();
890-
let a = pop_val!().[<as_ $uint_type>]();
876+
let (a, b) = peek_two!($uint_type);
891877
if b == 0 { return Err(Error::trap(DIVIDE_BY_ZERO)); }
892-
stack.push(WasmValue::[<from_ $uint_type>](a % b));
878+
overwrite!(WasmValue::[<from_ $uint_type>](a % b));
893879
}
894880
}};
895881
}

src/module.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::collections::HashMap;
2+
use std::ops::Range;
23
use std::rc::Rc;
34

45
use crate::byte_iter::*;
@@ -37,7 +38,7 @@ impl ExternType {
3738
// ---------------- Structures ----------------
3839
#[derive(Clone)]
3940
pub struct Function {
40-
pub body: std::ops::Range<usize>,
41+
pub body: Range<usize>,
4142
pub ty: Signature,
4243
pub locals: Vec<ValType>,
4344
pub import: Option<ImportRef>,
@@ -70,7 +71,7 @@ pub struct Global {
7071
pub struct Export { pub extern_type: ExternType, pub idx: u32 }
7172

7273
#[derive(Clone)]
73-
pub struct DataSegment { pub data_range: std::ops::Range<usize>, pub initializer_offset: usize }
74+
pub struct DataSegment { pub data_range: Range<usize>, pub initializer_offset: usize }
7475

7576
#[repr(C)]
7677
#[derive(Clone, Copy, Default)]
@@ -257,8 +258,8 @@ impl Module {
257258
}
258259

259260
fn initialize(&mut self) -> Result<(), Error> {
260-
// Copy to get around borrow checker
261-
let bytes: &[u8] = &self.bytes.clone()[..];
261+
// Rc::clone to get a separate handle, avoids borrow conflict with &mut self in closures
262+
let bytes: &[u8] = &self.bytes.clone();
262263

263264
// Check magic number and version
264265
if bytes.len() < 4 { return Err(Error::malformed(UNEXPECTED_END_SHORT)); }
@@ -346,22 +347,20 @@ impl Module {
346347
// Module name
347348
let module_len: u32 = safe_read_leb128(bytes, &mut it.idx, 32)?;
348349
let module_start = it.idx;
349-
if module_start + module_len as usize > bytes.len() {
350-
return Err(Error::malformed(UNEXPECTED_END));
351-
}
352-
let module_name = String::from_utf8(bytes[module_start..module_start + module_len as usize].to_vec())
353-
.map_err(|_| Error::malformed(INVALID_UTF8))?;
354-
it.idx = module_start + module_len as usize;
350+
let module_end = module_start + module_len as usize;
351+
if module_end > bytes.len() { return Err(Error::malformed(UNEXPECTED_END)); }
352+
let module_name = std::str::from_utf8(&bytes[module_start..module_end])
353+
.map_err(|_| Error::malformed(INVALID_UTF8))?.to_owned();
354+
it.idx = module_end;
355355

356356
// Field name
357357
let field_len: u32 = safe_read_leb128(bytes, &mut it.idx, 32)?;
358358
let field_start = it.idx;
359-
if field_start + field_len as usize > bytes.len() {
360-
return Err(Error::malformed(UNEXPECTED_END));
361-
}
362-
let field_name = String::from_utf8(bytes[field_start..field_start + field_len as usize].to_vec())
363-
.map_err(|_| Error::malformed(INVALID_UTF8))?;
364-
it.idx = field_start + field_len as usize;
359+
let field_end = field_start + field_len as usize;
360+
if field_end > bytes.len() { return Err(Error::malformed(UNEXPECTED_END)); }
361+
let field_name = std::str::from_utf8(&bytes[field_start..field_end])
362+
.map_err(|_| Error::malformed(INVALID_UTF8))?.to_owned();
363+
it.idx = field_end;
365364

366365
let extern_type = ExternType::from_byte(it.read_u8()?)
367366
.ok_or(Error::malformed(MALFORMED_IMPORT_KIND))?;
@@ -508,11 +507,11 @@ impl Module {
508507

509508
let name_len: u32 = safe_read_leb128(bytes, &mut it.idx, 32)?;
510509
let name_start = it.idx;
511-
if name_start + name_len as usize > bytes.len() {
512-
return Err(Error::malformed(UNEXPECTED_END));
513-
}
514-
let name = String::from_utf8(bytes[name_start..name_start + name_len as usize].to_vec()).unwrap();
515-
it.idx = name_start + name_len as usize;
510+
let name_end = name_start + name_len as usize;
511+
if name_end > bytes.len() { return Err(Error::malformed(UNEXPECTED_END)); }
512+
let name = std::str::from_utf8(&bytes[name_start..name_end])
513+
.map_err(|_| Error::malformed(INVALID_UTF8))?.to_owned();
514+
it.idx = name_end;
516515

517516
let byte = it.read_u8()?;
518517
let extern_type = ExternType::from_byte(byte)

src/validator.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,16 +297,14 @@ fn validate_else(_: &mut Module, it: &mut ByteIter, _: &Function, vs: &mut Valid
297297
_ => return Err(Error::validation(ELSE_MUST_CLOSE_IF)),
298298
};
299299

300-
// Push else frame with same signature
301-
let params = frame.sig.params.clone();
300+
vs.push_vals(&frame.sig.params);
302301
vs.push_frame(ControlFrame {
303302
sig: frame.sig,
304303
height: frame.height,
305304
unreachable: false,
306305
control_type: new_control_type,
307306
sig_pc: frame.sig_pc,
308307
});
309-
vs.push_vals(&params);
310308
Ok(Action::Continue)
311309
}
312310

0 commit comments

Comments
 (0)