wasm_interp: tests for memory allocation instructions

This commit is contained in:
Brian Carroll 2022-11-25 16:51:36 +00:00
parent 06f3726e35
commit 2bd67a3292
No known key found for this signature in database
GPG key ID: 5C7B2EC4101703C0
3 changed files with 59 additions and 7 deletions

View file

@ -36,7 +36,7 @@ impl<'a> ExecutionState<'a> {
{ {
let mem_bytes = memory_pages * MemorySection::PAGE_SIZE; let mem_bytes = memory_pages * MemorySection::PAGE_SIZE;
ExecutionState { ExecutionState {
memory: Vec::with_capacity_in(mem_bytes as usize, arena), memory: Vec::from_iter_in(iter::repeat(0).take(mem_bytes as usize), arena),
call_stack: CallStack::new(arena), call_stack: CallStack::new(arena),
value_stack: ValueStack::new(arena), value_stack: ValueStack::new(arena),
globals: Vec::from_iter_in(globals, arena), globals: Vec::from_iter_in(globals, arena),
@ -435,9 +435,23 @@ impl<'a> ExecutionState<'a> {
self.value_stack.push(Value::I32(size)); self.value_stack.push(Value::I32(size));
} }
GROWMEMORY => { GROWMEMORY => {
let old_bytes = self.memory.len() as u32;
let old_pages = old_bytes / MemorySection::PAGE_SIZE as u32;
let grow_pages = self.value_stack.pop_u32(); let grow_pages = self.value_stack.pop_u32();
let grow_bytes = grow_pages as usize * MemorySection::PAGE_SIZE as usize; let grow_bytes = grow_pages * MemorySection::PAGE_SIZE;
self.memory.extend(iter::repeat(0).take(grow_bytes)); let new_bytes = old_bytes + grow_bytes;
let success = match module.memory.max_bytes().unwrap() {
Some(max_bytes) => new_bytes <= max_bytes,
None => true,
};
if success {
self.memory
.extend(iter::repeat(0).take(grow_bytes as usize));
self.value_stack.push(Value::I32(old_pages as i32));
} else {
self.value_stack.push(Value::I32(-1));
}
} }
I32CONST => { I32CONST => {
let value = i32::parse((), &module.code.bytes, &mut self.program_counter).unwrap(); let value = i32::parse((), &module.code.bytes, &mut self.program_counter).unwrap();

View file

@ -662,11 +662,39 @@ fn test_i64store32() {
); );
} }
// #[test] #[test]
// fn test_currentmemory() {} fn test_currentmemory() {
let arena = Bump::new();
let mut module = WasmModule::new(&arena);
// #[test] let pages = 3;
// fn test_growmemory() {} let pc = 0;
module.memory = MemorySection::new(&arena, pages * MemorySection::PAGE_SIZE);
module.code.bytes.push(OpCode::CURRENTMEMORY as u8);
let mut state = ExecutionState::new(&arena, pages, pc, []);
state.execute_next_instruction(&module);
assert_eq!(state.value_stack.pop(), Value::I32(3))
}
#[test]
fn test_growmemory() {
let arena = Bump::new();
let mut module = WasmModule::new(&arena);
let existing_pages = 3;
let grow_pages = 2;
let pc = 0;
module.memory = MemorySection::new(&arena, existing_pages * MemorySection::PAGE_SIZE);
module.code.bytes.push(OpCode::I32CONST as u8);
module.code.bytes.encode_i32(grow_pages);
module.code.bytes.push(OpCode::GROWMEMORY as u8);
let mut state = ExecutionState::new(&arena, existing_pages, pc, []);
state.execute_next_instruction(&module);
state.execute_next_instruction(&module);
assert_eq!(state.memory.len(), 5 * MemorySection::PAGE_SIZE as usize);
}
#[test] #[test]
fn test_i32const() { fn test_i32const() {

View file

@ -790,6 +790,16 @@ impl<'a> MemorySection<'a> {
}; };
Ok(min_pages * MemorySection::PAGE_SIZE) Ok(min_pages * MemorySection::PAGE_SIZE)
} }
pub fn max_bytes(&self) -> Result<Option<u32>, ParseError> {
let mut cursor = 0;
let memory_limits = Limits::parse((), &self.bytes, &mut cursor)?;
let bytes = match memory_limits {
Limits::Min(_) => None,
Limits::MinMax(_, pages) => Some(pages * MemorySection::PAGE_SIZE),
};
Ok(bytes)
}
} }
section_impl!(MemorySection, SectionId::Memory); section_impl!(MemorySection, SectionId::Memory);