mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-24 14:11:32 +00:00
Improved instance functions
This commit is contained in:
@ -13,6 +13,7 @@ use memmap::MmapMut;
|
|||||||
use region;
|
use region;
|
||||||
use spin::RwLock;
|
use spin::RwLock;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::ptr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{mem, slice};
|
use std::{mem, slice};
|
||||||
|
|
||||||
@ -75,18 +76,26 @@ pub struct Instance {
|
|||||||
|
|
||||||
/// WebAssembly global variable data
|
/// WebAssembly global variable data
|
||||||
pub globals: Vec<u8>,
|
pub globals: Vec<u8>,
|
||||||
|
|
||||||
|
/// Webassembly functions
|
||||||
|
functions: Vec<usize>,
|
||||||
|
|
||||||
|
/// Region start memory location
|
||||||
|
code_base: *const (),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
/// Create a new `Instance`.
|
/// Create a new `Instance`.
|
||||||
pub fn new(module: &Module, code_base: *const ()) -> Result<Instance, ErrorKind> {
|
pub fn new(module: &Module) -> Result<Instance, ErrorKind> {
|
||||||
let mut tables: Vec<Vec<usize>> = Vec::new();
|
let mut tables: Vec<Vec<usize>> = Vec::new();
|
||||||
let mut memories: Vec<LinearMemory> = Vec::new();
|
let mut memories: Vec<LinearMemory> = Vec::new();
|
||||||
let mut globals: Vec<u8> = Vec::new();
|
let mut globals: Vec<u8> = Vec::new();
|
||||||
|
let mut functions: Vec<usize> = Vec::new();
|
||||||
|
let mut code_base: *const () = ptr::null();
|
||||||
|
|
||||||
let mut functions: Vec<usize> = Vec::with_capacity(module.info.function_bodies.len());
|
|
||||||
// Instantiate functions
|
// Instantiate functions
|
||||||
{
|
{
|
||||||
|
functions.reserve_exact(module.info.function_bodies.len());
|
||||||
let isa = isa::lookup(module.info.triple.clone())
|
let isa = isa::lookup(module.info.triple.clone())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.finish(module.info.flags.clone());
|
.finish(module.info.flags.clone());
|
||||||
@ -112,33 +121,34 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We only want to allocate in memory if there is more than
|
// We only want to allocate in memory if there is more than
|
||||||
// 0 functions. Otherwise reserving a 0-sized memory
|
// 0 functions. Otherwise reserving a 0-sized memory region
|
||||||
// cause a panic error
|
// cause a panic error
|
||||||
if total_size > 0 {
|
if total_size > 0 {
|
||||||
// Allocate the total memory for this functions
|
// Allocate the total memory for this functions
|
||||||
let map = MmapMut::map_anon(total_size).unwrap();
|
let map = MmapMut::map_anon(total_size).unwrap();
|
||||||
let region_start = map.as_ptr();
|
let region_start = map.as_ptr() as usize;
|
||||||
|
code_base = map.as_ptr() as *const ();
|
||||||
|
|
||||||
// // Emit this functions to memory
|
// // Emit this functions to memory
|
||||||
for (ref func_context, func_offset) in context_and_offsets.iter() {
|
for (ref func_context, func_offset) in context_and_offsets.iter() {
|
||||||
let mut trap_sink = TrapSink::new(*func_offset);
|
let mut trap_sink = TrapSink::new(*func_offset);
|
||||||
let mut reloc_sink = RelocSink::new();
|
let mut reloc_sink = RelocSink::new();
|
||||||
let mut func_pointer = (region_start as usize + func_offset) as *mut u8;
|
// let mut func_pointer = as *mut u8;
|
||||||
unsafe {
|
unsafe {
|
||||||
func_context.emit_to_memory(
|
func_context.emit_to_memory(
|
||||||
&*isa,
|
&*isa,
|
||||||
*&mut func_pointer,
|
(region_start + func_offset) as *mut u8,
|
||||||
&mut reloc_sink,
|
&mut reloc_sink,
|
||||||
&mut trap_sink,
|
&mut trap_sink,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
functions.push(func_pointer as usize);
|
functions.push(*func_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set protection of this memory region to Read + Execute
|
// Set protection of this memory region to Read + Execute
|
||||||
// so we are able to execute the functions emitted to memory
|
// so we are able to execute the functions emitted to memory
|
||||||
unsafe {
|
unsafe {
|
||||||
region::protect(region_start, total_size, region::Protection::ReadExecute)
|
region::protect(region_start as *mut u8, total_size, region::Protection::ReadExecute)
|
||||||
.expect("unable to make memory readable+executable");
|
.expect("unable to make memory readable+executable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,6 +231,8 @@ impl Instance {
|
|||||||
tables: Arc::new(tables.into_iter().map(|table| RwLock::new(table)).collect()),
|
tables: Arc::new(tables.into_iter().map(|table| RwLock::new(table)).collect()),
|
||||||
memories: Arc::new(memories.into_iter().collect()),
|
memories: Arc::new(memories.into_iter().collect()),
|
||||||
globals: globals,
|
globals: globals,
|
||||||
|
functions: functions,
|
||||||
|
code_base: code_base,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,8 +243,60 @@ impl Instance {
|
|||||||
/// Invoke a WebAssembly function given a FuncIndex and the
|
/// Invoke a WebAssembly function given a FuncIndex and the
|
||||||
/// arguments that the function should be called with
|
/// arguments that the function should be called with
|
||||||
pub fn invoke(&self, func_index: FuncIndex, args: Vec<i32>) {
|
pub fn invoke(&self, func_index: FuncIndex, args: Vec<i32>) {
|
||||||
unimplemented!()
|
// let vmctx = make_vmctx(instance, &mut mem_base_addrs);
|
||||||
|
// let vmctx = ptr::null();
|
||||||
|
// Rather than writing inline assembly to jump to the code region, we use the fact that
|
||||||
|
// the Rust ABI for calling a function with no arguments and no return matches the one of
|
||||||
|
// the generated code. Thanks to this, we can transmute the code region into a first-class
|
||||||
|
// Rust function and call it.
|
||||||
|
let func_pointer = get_function_addr(self.code_base, &self.functions, &func_index);
|
||||||
|
// let index = func_index.index();
|
||||||
|
// let func_pointer = self.functions[index];
|
||||||
|
println!("INVOKING FUNCTION {:?} {:?}", func_index, func_pointer);
|
||||||
|
unsafe {
|
||||||
|
let func = mem::transmute::<_, fn()>(func_pointer);
|
||||||
|
let result = func();
|
||||||
|
println!("FUNCTION INVOKED, result {:?}", result);
|
||||||
|
|
||||||
|
// start_func(vmctx.as_ptr());
|
||||||
}
|
}
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// pub fn generate_context(&mut self) -> &VmCtx {
|
||||||
|
// let memories: Vec<UncheckedSlice<u8>> = self.memories.iter()
|
||||||
|
// .map(|mem| mem.into())
|
||||||
|
// .collect();
|
||||||
|
|
||||||
|
// let tables: Vec<BoundedSlice<usize>> = self.tables.iter()
|
||||||
|
// .map(|table| table.write()[..].into())
|
||||||
|
// .collect();
|
||||||
|
|
||||||
|
// let globals: UncheckedSlice<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,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// pub fn start_func(&self) -> extern fn(&VmCtx) {
|
// pub fn start_func(&self) -> extern fn(&VmCtx) {
|
||||||
// self.start_func
|
// self.start_func
|
||||||
@ -245,6 +309,8 @@ impl Clone for Instance {
|
|||||||
tables: Arc::clone(&self.tables),
|
tables: Arc::clone(&self.tables),
|
||||||
memories: Arc::clone(&self.memories),
|
memories: Arc::clone(&self.memories),
|
||||||
globals: self.globals.clone(),
|
globals: self.globals.clone(),
|
||||||
|
functions: self.functions.clone(),
|
||||||
|
code_base: self.code_base,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ pub fn instantiate(
|
|||||||
) -> Result<ResultObject, ErrorKind> {
|
) -> Result<ResultObject, ErrorKind> {
|
||||||
let module = compile(buffer_source)?;
|
let module = compile(buffer_source)?;
|
||||||
debug!("webassembly - creating instance");
|
debug!("webassembly - creating instance");
|
||||||
let instance = Instance::new(&module, ptr::null())?;
|
let instance = Instance::new(&module)?;
|
||||||
debug!("webassembly - instance created");
|
debug!("webassembly - instance created");
|
||||||
Ok(ResultObject { module, instance })
|
Ok(ResultObject { module, instance })
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user