Get memory intrinsics at runtime.

This commit is contained in:
Heyang Zhou 2019-05-04 10:33:12 -07:00
parent a590d7cd07
commit 46e4cb05bc
2 changed files with 111 additions and 51 deletions

View File

@ -1,9 +1,11 @@
pub use crate::backing::{ImportBacking, LocalBacking};
use crate::{
memory::Memory,
module::ModuleInner,
memory::{Memory, MemoryType},
module::{ModuleInfo, ModuleInner},
structures::TypedIndex,
types::{LocalOrImport, MemoryIndex},
types::{LocalOrImport, MemoryIndex, LocalMemoryIndex},
units::{Pages},
vmcalls,
};
use std::{ffi::c_void, mem, ptr};
@ -61,6 +63,77 @@ pub struct InternalCtx {
/// signature id. This is used to allow call-indirect to other
/// modules safely.
pub dynamic_sigindices: *const SigId,
pub intrinsics: *const Intrinsics,
}
#[repr(C)]
pub struct Intrinsics {
pub memory_grow: *const Func,
pub memory_size: *const Func,
/*pub memory_grow: unsafe extern "C" fn(
ctx: &mut Ctx,
memory_index: usize,
delta: Pages,
) -> i32,
pub memory_size: unsafe extern "C" fn(
ctx: &Ctx,
memory_index: usize,
) -> Pages,*/
}
unsafe impl Send for Intrinsics {}
unsafe impl Sync for Intrinsics {}
impl Intrinsics {
pub fn offset_memory_grow() -> u8 {
(0 * ::std::mem::size_of::<usize>()) as u8
}
pub fn offset_memory_size() -> u8 {
(1 * ::std::mem::size_of::<usize>()) as u8
}
}
pub static INTRINSICS_LOCAL_STATIC_MEMORY: Intrinsics = Intrinsics {
memory_grow: vmcalls::local_static_memory_grow as _,
memory_size: vmcalls::local_static_memory_size as _,
};
pub static INTRINSICS_LOCAL_DYNAMIC_MEMORY: Intrinsics = Intrinsics {
memory_grow: vmcalls::local_dynamic_memory_grow as _,
memory_size: vmcalls::local_dynamic_memory_size as _,
};
pub static INTRINSICS_IMPORTED_STATIC_MEMORY: Intrinsics = Intrinsics {
memory_grow: vmcalls::imported_static_memory_grow as _,
memory_size: vmcalls::imported_static_memory_size as _,
};
pub static INTRINSICS_IMPORTED_DYNAMIC_MEMORY: Intrinsics = Intrinsics {
memory_grow: vmcalls::imported_dynamic_memory_grow as _,
memory_size: vmcalls::imported_dynamic_memory_size as _,
};
fn get_intrinsics_for_module(m: &ModuleInfo) -> *const Intrinsics {
if m.memories.len() == 0 && m.imported_memories.len() == 0 {
::std::ptr::null()
} else {
match MemoryIndex::new(0).local_or_import(m) {
LocalOrImport::Local(local_mem_index) => {
let mem_desc = &m.memories[local_mem_index];
match mem_desc.memory_type() {
MemoryType::Dynamic => &INTRINSICS_LOCAL_DYNAMIC_MEMORY,
MemoryType::Static => &INTRINSICS_LOCAL_STATIC_MEMORY,
MemoryType::SharedStatic => unimplemented!(),
}
}
LocalOrImport::Import(import_mem_index) => {
let mem_desc = &m.imported_memories[import_mem_index].1;
match mem_desc.memory_type() {
MemoryType::Dynamic => &INTRINSICS_IMPORTED_DYNAMIC_MEMORY,
MemoryType::Static => &INTRINSICS_IMPORTED_STATIC_MEMORY,
MemoryType::SharedStatic => unimplemented!(),
}
}
}
}
}
impl Ctx {
@ -82,6 +155,8 @@ impl Ctx {
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
intrinsics: get_intrinsics_for_module(&module.info),
},
local_functions: local_backing.local_functions.as_ptr(),
@ -114,6 +189,8 @@ impl Ctx {
imported_funcs: import_backing.vm_functions.as_mut_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
intrinsics: get_intrinsics_for_module(&module.info),
},
local_functions: local_backing.local_functions.as_ptr(),
@ -207,9 +284,13 @@ impl Ctx {
7 * (mem::size_of::<usize>() as u8)
}
pub fn offset_local_functions() -> u8 {
pub fn offset_intrinsics() -> u8 {
8 * (mem::size_of::<usize>() as u8)
}
pub fn offset_local_functions() -> u8 {
9 * (mem::size_of::<usize>() as u8)
}
}
enum InnerFunc {}
@ -403,6 +484,11 @@ mod vm_offset_tests {
offset_of!(InternalCtx => imported_funcs).get_byte_offset(),
);
assert_eq!(
Ctx::offset_intrinsics() as usize,
offset_of!(InternalCtx => intrinsics).get_byte_offset(),
);
assert_eq!(
Ctx::offset_local_functions() as usize,
offset_of!(Ctx => local_functions).get_byte_offset(),

View File

@ -3284,33 +3284,20 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
Operator::Nop => {}
Operator::MemorySize { reserved } => {
let memory_index = MemoryIndex::new(reserved as usize);
let target: usize = match memory_index.local_or_import(module_info) {
LocalOrImport::Local(local_mem_index) => {
let mem_desc = &module_info.memories[local_mem_index];
match mem_desc.memory_type() {
MemoryType::Dynamic => vmcalls::local_dynamic_memory_size as usize,
MemoryType::Static => vmcalls::local_static_memory_size as usize,
MemoryType::SharedStatic => unimplemented!(),
}
}
LocalOrImport::Import(import_mem_index) => {
let mem_desc = &module_info.imported_memories[import_mem_index].1;
match mem_desc.memory_type() {
MemoryType::Dynamic => vmcalls::imported_dynamic_memory_size as usize,
MemoryType::Static => vmcalls::imported_static_memory_size as usize,
MemoryType::SharedStatic => unimplemented!(),
}
}
};
a.emit_mov(
Size::S64,
Location::Memory(Machine::get_vmctx_reg(), vm::Ctx::offset_intrinsics() as i32),
Location::GPR(GPR::RAX)
);
a.emit_mov(
Size::S64,
Location::Memory(GPR::RAX, vm::Intrinsics::offset_memory_size() as i32),
Location::GPR(GPR::RAX)
);
Self::emit_call_sysv(
a,
&mut self.machine,
|a| {
a.emit_mov(
Size::S64,
Location::Imm64(target as u64),
Location::GPR(GPR::RAX),
);
a.emit_call_location(Location::GPR(GPR::RAX));
},
::std::iter::once(Location::Imm32(memory_index.index() as u32)),
@ -3321,40 +3308,27 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
}
Operator::MemoryGrow { reserved } => {
let memory_index = MemoryIndex::new(reserved as usize);
let target: usize = match memory_index.local_or_import(module_info) {
LocalOrImport::Local(local_mem_index) => {
let mem_desc = &module_info.memories[local_mem_index];
match mem_desc.memory_type() {
MemoryType::Dynamic => vmcalls::local_dynamic_memory_grow as usize,
MemoryType::Static => vmcalls::local_static_memory_grow as usize,
MemoryType::SharedStatic => unimplemented!(),
}
}
LocalOrImport::Import(import_mem_index) => {
let mem_desc = &module_info.imported_memories[import_mem_index].1;
match mem_desc.memory_type() {
MemoryType::Dynamic => vmcalls::imported_dynamic_memory_grow as usize,
MemoryType::Static => vmcalls::imported_static_memory_grow as usize,
MemoryType::SharedStatic => unimplemented!(),
}
}
};
let (param_pages, param_pages_lot) = self.value_stack.pop().unwrap();
if param_pages_lot == LocalOrTemp::Temp {
self.machine.release_locations_only_regs(&[param_pages]);
}
a.emit_mov(
Size::S64,
Location::Memory(Machine::get_vmctx_reg(), vm::Ctx::offset_intrinsics() as i32),
Location::GPR(GPR::RAX)
);
a.emit_mov(
Size::S64,
Location::Memory(GPR::RAX, vm::Intrinsics::offset_memory_grow() as i32),
Location::GPR(GPR::RAX)
);
Self::emit_call_sysv(
a,
&mut self.machine,
|a| {
a.emit_mov(
Size::S64,
Location::Imm64(target as u64),
Location::GPR(GPR::RAX),
);
a.emit_call_location(Location::GPR(GPR::RAX));
},
::std::iter::once(Location::Imm32(memory_index.index() as u32))