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}; pub use crate::backing::{ImportBacking, LocalBacking};
use crate::{ use crate::{
memory::Memory, memory::{Memory, MemoryType},
module::ModuleInner, module::{ModuleInfo, ModuleInner},
structures::TypedIndex, structures::TypedIndex,
types::{LocalOrImport, MemoryIndex}, types::{LocalOrImport, MemoryIndex, LocalMemoryIndex},
units::{Pages},
vmcalls,
}; };
use std::{ffi::c_void, mem, ptr}; 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 /// signature id. This is used to allow call-indirect to other
/// modules safely. /// modules safely.
pub dynamic_sigindices: *const SigId, 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 { impl Ctx {
@ -82,6 +155,8 @@ impl Ctx {
imported_funcs: import_backing.vm_functions.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
intrinsics: get_intrinsics_for_module(&module.info),
}, },
local_functions: local_backing.local_functions.as_ptr(), local_functions: local_backing.local_functions.as_ptr(),
@ -114,6 +189,8 @@ impl Ctx {
imported_funcs: import_backing.vm_functions.as_mut_ptr(), imported_funcs: import_backing.vm_functions.as_mut_ptr(),
dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(), dynamic_sigindices: local_backing.dynamic_sigindices.as_ptr(),
intrinsics: get_intrinsics_for_module(&module.info),
}, },
local_functions: local_backing.local_functions.as_ptr(), local_functions: local_backing.local_functions.as_ptr(),
@ -207,9 +284,13 @@ impl Ctx {
7 * (mem::size_of::<usize>() as u8) 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) 8 * (mem::size_of::<usize>() as u8)
} }
pub fn offset_local_functions() -> u8 {
9 * (mem::size_of::<usize>() as u8)
}
} }
enum InnerFunc {} enum InnerFunc {}
@ -403,6 +484,11 @@ mod vm_offset_tests {
offset_of!(InternalCtx => imported_funcs).get_byte_offset(), offset_of!(InternalCtx => imported_funcs).get_byte_offset(),
); );
assert_eq!(
Ctx::offset_intrinsics() as usize,
offset_of!(InternalCtx => intrinsics).get_byte_offset(),
);
assert_eq!( assert_eq!(
Ctx::offset_local_functions() as usize, Ctx::offset_local_functions() as usize,
offset_of!(Ctx => local_functions).get_byte_offset(), offset_of!(Ctx => local_functions).get_byte_offset(),

View File

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