Added first tests for the vmctx (memory usage)

This commit is contained in:
Syrus Akbary
2018-10-18 19:01:09 +02:00
parent 80f3bf161e
commit 6fce21e4d5
6 changed files with 179 additions and 59 deletions

View File

@ -69,6 +69,7 @@ fn get_function_addr(
// }
/// Zero-sized, non-instantiable type.
#[derive(Debug)]
pub enum VmCtx {}
impl VmCtx {
@ -85,15 +86,20 @@ impl VmCtx {
}
}
#[derive(Debug)]
#[repr(C)]
pub struct VmCtxData<'phantom> {
pub user_data: UserData,
globals: UncheckedSlice<u8>,
memories: UncheckedSlice<UncheckedSlice<u8>>,
tables: UncheckedSlice<BoundedSlice<usize>>,
// globals: UncheckedSlice<u8>,
// memories: UncheckedSlice<UncheckedSlice<u8>>,
// tables: UncheckedSlice<BoundedSlice<usize>>,
globals: Vec<u8>,
memories: Vec<Vec<u8>>,
tables: Vec<Vec<usize>>,
phantom: PhantomData<&'phantom ()>,
}
#[derive(Debug)]
#[repr(C)]
pub struct UserData {
// pub process: Dispatch<Process>,
@ -445,6 +451,12 @@ impl Instance {
})
}
// pub fn memory_mut(&self, memory_index: usize) -> &mut LinearMemory {
// self.memories
// .get_mut(memory_index)
// .unwrap_or_else(|| panic!("no memory for index {}", memory_index))
// }
pub fn memories(&self) -> Arc<Vec<LinearMemory>> {
self.memories.clone()
}
@ -491,46 +503,56 @@ impl Instance {
result
}
pub fn start(&self) {
pub fn start(&mut self, vmctx: &VmCtx) {
if let Some(func_index) = self.start_func {
// let vmctx: &VmCtx = ptr::null();
let func: fn() = self.get_function(func_index);
func()
let func: fn(&VmCtx) = get_instance_function!(self, func_index);
func(vmctx)
}
}
// pub fn generate_context(&mut self) -> &VmCtx {
// let memories: Vec<UncheckedSlice<u8>> = self.memories.iter()
// .map(|mem| mem.into())
// .collect();
pub fn generate_context(&mut self) -> &VmCtx {
let mut memories: Vec<Vec<u8>> = self.memories.iter().map(|mem| mem[..].into()).collect();
// let tables: Vec<BoundedSlice<usize>> = self.tables.iter()
// .map(|table| table.write()[..].into())
// .collect();
let tables: Vec<Vec<usize>> = self.tables.iter().map(|table| table[..].into()).collect();
// let globals: UncheckedSlice<u8> = self.globals[..].into();
let globals: Vec<u8> = self.globals[..].into();
// assert!(memories.len() >= 1, "modules must have at least one memory");
// // the first memory has a space of `mem::size_of::<VmCtxData>()` rounded
// // up to the 4KiB before it. We write the VmCtxData into that.
// let data = VmCtxData {
// globals: globals,
// memories: memories[1..].into(),
// tables: tables[..].into(),
// user_data: UserData {
// // process,
// instance,
// },
// phantom: PhantomData,
// };
assert!(memories.len() >= 1, "modules must have at least one memory");
// the first memory has a space of `mem::size_of::<VmCtxData>()` rounded
// up to the 4KiB before it. We write the VmCtxData into that.
let instance = self.clone();
let data = VmCtxData {
globals: globals,
memories: memories[1..].into(),
tables: tables[..].into(),
user_data: UserData {
// process,
instance,
},
phantom: PhantomData,
};
// let main_heap_ptr = memories[0].as_mut_ptr() as *mut VmCtxData;
// unsafe {
// main_heap_ptr
// .sub(1)
// .write(data);
// &*(main_heap_ptr as *const VmCtx)
// }
let main_heap_ptr = memories[0].as_mut_ptr() as *mut VmCtxData;
unsafe {
main_heap_ptr.sub(1).write(data);
&*(main_heap_ptr as *const VmCtx)
}
}
/// Returns a slice of the contents of allocated linear memory.
pub fn inspect_memory(&self, memory_index: usize, address: usize, len: usize) -> &[u8] {
&self
.memories
.get(memory_index)
.unwrap_or_else(|| panic!("no memory for index {}", memory_index))
.as_ref()[address..address + len]
}
// Shows the value of a global variable.
// pub fn inspect_global(&self, global_index: GlobalIndex, ty: ir::Type) -> &[u8] {
// let offset = global_index * 8;
// let len = ty.bytes() as usize;
// &self.globals[offset..offset + len]
// }
// pub fn start_func(&self) -> extern fn(&VmCtx) {
@ -552,9 +574,22 @@ impl Clone for Instance {
}
}
extern "C" fn grow_memory(size: u32, memory_index: u32, vmctx: *mut *mut u8) -> u32 {
return 0;
// unimplemented!();
extern "C" fn grow_memory(size: u32, memory_index: u32, vmctx: &VmCtx) -> i32 {
// return 0;
unimplemented!();
// let instance = &vmctx
// .data()
// .user_data
// .instance;
// let mut memory = &mut instance.memories[memory_index as usize];
// if let Some(old_size) = memory.grow(size) {
// old_size as i32
// } else {
-1
// }
// unsafe {
// let instance = (*vmctx.offset(4)) as *mut Instance;
// (*instance)
@ -564,8 +599,29 @@ extern "C" fn grow_memory(size: u32, memory_index: u32, vmctx: *mut *mut u8) ->
// }
}
extern "C" fn current_memory(memory_index: u32, vmctx: *mut *mut u8) -> u32 {
return 0;
extern "C" fn current_memory(memory_index: u32, vmctx: &VmCtx) -> u32 {
// return 0;
println!("current_memory::init {:?}", memory_index);
let instance = &vmctx.data().user_data.instance;
let memory = &instance.memories[memory_index as usize];
println!(
"INSPECTED MEMORY ({:?}) {:?}",
memory.current_size(),
instance.inspect_memory(0, 0, 1)
);
memory.current_size() as u32
// return 1;
// let vm = unsafe {
// (*vmctx) as *mut VmCtx
// };
// println!("current_memory::instance {:?} {:?}", memory_index, vmctx);
// let memory = &instance.memories[0];
// println!("MEMORY INDEX {:?}", memory_index);
// unimplemented!()
// memory.current_size() as u32
// unimplemented!();
// unsafe {
// let instance = (*vmctx.offset(4)) as *mut Instance;