diff --git a/lib/clif-backend/src/call/recovery.rs b/lib/clif-backend/src/call/recovery.rs index 996923329..92108d70c 100644 --- a/lib/clif-backend/src/call/recovery.rs +++ b/lib/clif-backend/src/call/recovery.rs @@ -32,6 +32,9 @@ thread_local! { pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null()); } +unsafe impl Send for HandlerData {} +unsafe impl Sync for HandlerData {} + pub struct HandlerData { trap_data: TrapSink, buffer_ptr: *const c_void, diff --git a/lib/clif-backend/src/func_env.rs b/lib/clif-backend/src/func_env.rs index 0b704330a..f41ea42a4 100644 --- a/lib/clif-backend/src/func_env.rs +++ b/lib/clif-backend/src/func_env.rs @@ -73,59 +73,59 @@ impl<'env, 'module, 'isa> FuncEnvironment for FuncEnv<'env, 'module, 'isa> { let vmctx = func.create_global_value(ir::GlobalValueData::VMContext); let ptr_type = self.pointer_type(); - match global_index.local_or_import(self.env.module) { + let local_global_addr = match global_index.local_or_import(self.env.module) { LocalOrImport::Local(local_global_index) => { let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load { base: vmctx, offset: (vm::Ctx::offset_globals() as i32).into(), - global_type: self.pointer_type(), + global_type: ptr_type, readonly: true, }); - let offset = local_global_index.index() * vm::LocalGlobal::size() as usize; + let offset = local_global_index.index() * mem::size_of::<*mut vm::LocalGlobal>(); - let local_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm { + let local_global_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm { base: globals_base_addr, offset: (offset as i64).into(), global_type: ptr_type, }); - // Create global variable based on the data above. - cranelift_wasm::GlobalVariable::Memory { - gv: local_global_addr, - offset: (vm::LocalGlobal::offset_data() as i32).into(), - ty: self.env.get_global(clif_global_index).ty, - } - } - LocalOrImport::Import(imported_global_index) => { - let imported_globals_base_addr = - func.create_global_value(ir::GlobalValueData::Load { - base: vmctx, - offset: (vm::Ctx::offset_imported_globals() as i32).into(), - global_type: ptr_type, - readonly: true, - }); - - let offset = imported_global_index.index() * vm::ImportedGlobal::size() as usize; - let imported_global_addr = func.create_global_value(ir::GlobalValueData::IAddImm { - base: imported_globals_base_addr, - offset: (offset as i64).into(), + func.create_global_value(ir::GlobalValueData::Load { + base: local_global_ptr_ptr, + offset: 0.into(), global_type: ptr_type, - }); - - let local_global_addr = func.create_global_value(ir::GlobalValueData::Load { - base: imported_global_addr, - offset: (vm::ImportedGlobal::offset_global() as i32).into(), + readonly: true, + }) + } + LocalOrImport::Import(import_global_index) => { + let globals_base_addr = func.create_global_value(ir::GlobalValueData::Load { + base: vmctx, + offset: (vm::Ctx::offset_imported_globals() as i32).into(), global_type: ptr_type, readonly: true, }); - cranelift_wasm::GlobalVariable::Memory { - gv: local_global_addr, - offset: (vm::LocalGlobal::offset_data() as i32).into(), - ty: self.env.get_global(clif_global_index).ty, - } + let offset = import_global_index.index() * mem::size_of::<*mut vm::LocalGlobal>(); + + let local_global_ptr_ptr = func.create_global_value(ir::GlobalValueData::IAddImm { + base: globals_base_addr, + offset: (offset as i64).into(), + global_type: ptr_type, + }); + + func.create_global_value(ir::GlobalValueData::Load { + base: local_global_ptr_ptr, + offset: 0.into(), + global_type: ptr_type, + readonly: true, + }) } + }; + + cranelift_wasm::GlobalVariable::Memory { + gv: local_global_addr, + offset: (vm::LocalGlobal::offset_data() as i32).into(), + ty: self.env.get_global(clif_global_index).ty, } } diff --git a/lib/clif-backend/src/module_env.rs b/lib/clif-backend/src/module_env.rs index ff3cbe007..fc4cb7664 100644 --- a/lib/clif-backend/src/module_env.rs +++ b/lib/clif-backend/src/module_env.rs @@ -9,8 +9,8 @@ use wasmer_runtime_core::{ module::{DataInitializer, ExportIndex, ImportName, TableInitializer}, structures::{Map, TypedIndex}, types::{ - ElementType, Global, GlobalDesc, GlobalIndex, Initializer, LocalFuncIndex, LocalOrImport, - MemoryDesc, SigIndex, TableDesc, Value, + ElementType, GlobalDesc, GlobalIndex, GlobalInit, Initializer, LocalFuncIndex, + LocalOrImport, MemoryDesc, SigIndex, TableDesc, Value, }, }; @@ -93,19 +93,21 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> /// Declares a global to the environment. fn declare_global(&mut self, global: cranelift_wasm::Global) { - use cranelift_wasm::GlobalInit; - let desc = GlobalDesc { mutable: global.mutability, ty: Converter(global.ty).into(), }; let init = match global.initializer { - GlobalInit::I32Const(x) => Initializer::Const(Value::I32(x)), - GlobalInit::I64Const(x) => Initializer::Const(Value::I64(x)), - GlobalInit::F32Const(x) => Initializer::Const(Value::F32(f32::from_bits(x))), - GlobalInit::F64Const(x) => Initializer::Const(Value::F64(f64::from_bits(x))), - GlobalInit::GetGlobal(global_index) => { + cranelift_wasm::GlobalInit::I32Const(x) => Initializer::Const(Value::I32(x)), + cranelift_wasm::GlobalInit::I64Const(x) => Initializer::Const(Value::I64(x)), + cranelift_wasm::GlobalInit::F32Const(x) => { + Initializer::Const(Value::F32(f32::from_bits(x))) + } + cranelift_wasm::GlobalInit::F64Const(x) => { + Initializer::Const(Value::F64(f64::from_bits(x))) + } + cranelift_wasm::GlobalInit::GetGlobal(global_index) => { assert!(!desc.mutable); let global_index: GlobalIndex = Converter(global_index).into(); let imported_global_index = global_index @@ -118,7 +120,7 @@ impl<'module, 'isa, 'data> ModuleEnvironment<'data> for ModuleEnv<'module, 'isa> }; // Add global ir to the list of globals - self.module.globals.push(Global { desc, init }); + self.module.globals.push(GlobalInit { desc, init }); self.globals.push(global); } diff --git a/lib/runtime-core/examples/simple/main.rs b/lib/runtime-core/examples/simple/main.rs index 1737c4163..3f31e80d5 100644 --- a/lib/runtime-core/examples/simple/main.rs +++ b/lib/runtime-core/examples/simple/main.rs @@ -1,6 +1,12 @@ use wabt::wat2wasm; use wasmer_clif_backend::CraneliftCompiler; -use wasmer_runtime_core::{error::Result, prelude::*, memory::Memory, types::MemoryDesc}; +use wasmer_runtime_core::{ + error::Result, + global::Global, + memory::Memory, + prelude::*, + types::{MemoryDesc, Value}, +}; static EXAMPLE_WASM: &'static [u8] = include_bytes!("simple.wasm"); @@ -12,7 +18,10 @@ fn main() -> Result<()> { min: 1, max: Some(1), shared: false, - }).unwrap(); + }) + .unwrap(); + + let global = Global::new(Value::I32(42)); memory.direct_access_mut(|slice: &mut [u32]| { slice[0] = 42; @@ -22,6 +31,7 @@ fn main() -> Result<()> { "env" => { "print_i32" => func!(print_num, [i32] -> [i32]), "memory" => memory, + "global" => global, }, }; @@ -48,9 +58,9 @@ static IMPORT_MODULE: &str = r#" (module (type $t0 (func (param i32) (result i32))) (import "env" "memory" (memory 1 1)) + (import "env" "global" (global i32)) (import "env" "print_i32" (func $print_i32 (type $t0))) (func $print_num (export "print_num") (type $t0) (param $p0 i32) (result i32) - i32.const 0 - i32.load + get_global 0 call $print_i32)) "#; diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index 8c0f963e2..f9ef9e556 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -35,7 +35,7 @@ pub trait Compiler { /// The functionality exposed by this trait is expected to be used /// for calling functions exported by a webassembly module from /// host code only. -pub trait ProtectedCaller { +pub trait ProtectedCaller: Send + Sync { /// This calls the exported function designated by `local_func_index`. /// Important to note, this supports calling imported functions that are /// then exported. @@ -62,7 +62,7 @@ pub trait ProtectedCaller { ) -> RuntimeResult>; } -pub trait FuncResolver { +pub trait FuncResolver: Send + Sync { /// This returns a pointer to the function designated by the `local_func_index` /// parameter. fn get( diff --git a/lib/runtime-core/src/backing.rs b/lib/runtime-core/src/backing.rs index 36adc322e..3cba8d0a6 100644 --- a/lib/runtime-core/src/backing.rs +++ b/lib/runtime-core/src/backing.rs @@ -1,6 +1,7 @@ use crate::{ error::{LinkError, LinkResult}, export::{Context, Export}, + global::Global, import::ImportObject, memory::{Memory, WASM_PAGE_SIZE}, module::{ImportName, ModuleInner}, @@ -9,7 +10,7 @@ use crate::{ types::{ ElementType, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalOrImport, - LocalTableIndex, Type, Value, + LocalTableIndex, Value, }, vm, }; @@ -19,10 +20,11 @@ use std::{mem, slice}; pub struct LocalBacking { pub(crate) memories: BoxedMap, pub(crate) tables: BoxedMap, + pub(crate) globals: BoxedMap, pub(crate) vm_memories: BoxedMap, pub(crate) vm_tables: BoxedMap, - pub(crate) vm_globals: BoxedMap, + pub(crate) vm_globals: BoxedMap, } // impl LocalBacking { @@ -39,15 +41,16 @@ impl LocalBacking { pub(crate) fn new(module: &ModuleInner, imports: &ImportBacking, vmctx: *mut vm::Ctx) -> Self { let mut memories = Self::generate_memories(module); let mut tables = Self::generate_tables(module); - let globals = Self::generate_globals(module); + let mut globals = Self::generate_globals(module, imports); let vm_memories = Self::finalize_memories(module, imports, &mut memories); let vm_tables = Self::finalize_tables(module, imports, &mut tables, vmctx); - let vm_globals = Self::finalize_globals(module, imports, globals); + let vm_globals = Self::finalize_globals(&mut globals); Self { memories, tables, + globals, vm_memories, vm_tables, @@ -89,9 +92,9 @@ impl LocalBacking { let init_base = match init.base { Initializer::Const(Value::I32(offset)) => offset as u32, Initializer::Const(_) => panic!("a const initializer must be the i32 type"), - Initializer::GetGlobal(imported_global_index) => { - if module.imported_globals[imported_global_index].1.ty == Type::I32 { - unsafe { (*imports.vm_globals[imported_global_index].global).data as u32 } + Initializer::GetGlobal(import_global_index) => { + if let Value::I32(x) = imports.globals[import_global_index].get() { + x as u32 } else { panic!("unsupported global type for initialzer") } @@ -152,9 +155,9 @@ impl LocalBacking { let init_base = match init.base { Initializer::Const(Value::I32(offset)) => offset as u32, Initializer::Const(_) => panic!("a const initializer must be the i32 type"), - Initializer::GetGlobal(imported_global_index) => { - if module.imported_globals[imported_global_index].1.ty == Type::I32 { - unsafe { (*imports.vm_globals[imported_global_index].global).data as u32 } + Initializer::GetGlobal(import_global_index) => { + if let Value::I32(x) = imports.globals[import_global_index].get() { + x as u32 } else { panic!("unsupported global type for initialzer") } @@ -261,45 +264,52 @@ impl LocalBacking { .into_boxed_map() } - fn generate_globals(module: &ModuleInner) -> BoxedMap { + fn generate_globals( + module: &ModuleInner, + imports: &ImportBacking, + ) -> BoxedMap { let mut globals = Map::with_capacity(module.globals.len()); - globals.resize(module.globals.len(), vm::LocalGlobal::null()); + for (_, global_init) in module.globals.iter() { + let value = match &global_init.init { + Initializer::Const(value) => value.clone(), + Initializer::GetGlobal(import_global_index) => { + imports.globals[*import_global_index].get() + } + }; + + let global = if global_init.desc.mutable { + Global::new_mutable(value) + } else { + Global::new(value) + }; + + globals.push(global); + } globals.into_boxed_map() } fn finalize_globals( - module: &ModuleInner, - imports: &ImportBacking, - mut globals: BoxedMap, - ) -> BoxedMap { - for ((_, to), (_, from)) in globals.iter_mut().zip(module.globals.iter()) { - to.data = match from.init { - Initializer::Const(ref value) => match value { - Value::I32(x) => *x as u64, - Value::I64(x) => *x as u64, - Value::F32(x) => x.to_bits() as u64, - Value::F64(x) => x.to_bits(), - }, - Initializer::GetGlobal(imported_global_index) => unsafe { - (*imports.vm_globals[imported_global_index].global).data - }, - }; - } - + globals: &mut SliceMap, + ) -> BoxedMap { globals + .iter_mut() + .map(|(_, global)| global.vm_local_global()) + .collect::>() + .into_boxed_map() } } #[derive(Debug)] pub struct ImportBacking { pub(crate) memories: BoxedMap, + pub(crate) globals: BoxedMap, pub(crate) vm_functions: BoxedMap, pub(crate) vm_memories: BoxedMap, pub(crate) vm_tables: BoxedMap, - pub(crate) vm_globals: BoxedMap, + pub(crate) vm_globals: BoxedMap, } impl ImportBacking { @@ -317,7 +327,7 @@ impl ImportBacking { Map::new().into_boxed_map() }); - let (vm_memories, memories) = import_memories(module, imports).unwrap_or_else(|le| { + let (memories, vm_memories) = import_memories(module, imports).unwrap_or_else(|le| { failed = true; link_errors.extend(le); (Map::new().into_boxed_map(), Map::new().into_boxed_map()) @@ -329,10 +339,10 @@ impl ImportBacking { Map::new().into_boxed_map() }); - let vm_globals = import_globals(module, imports).unwrap_or_else(|le| { + let (globals, vm_globals) = import_globals(module, imports).unwrap_or_else(|le| { failed = true; link_errors.extend(le); - Map::new().into_boxed_map() + (Map::new().into_boxed_map(), Map::new().into_boxed_map()) }); if failed { @@ -340,6 +350,7 @@ impl ImportBacking { } else { Ok(ImportBacking { memories, + globals, vm_functions, vm_memories, @@ -425,8 +436,8 @@ fn import_memories( module: &ModuleInner, imports: &mut ImportObject, ) -> LinkResult<( - BoxedMap, BoxedMap, + BoxedMap, )> { let mut link_errors = vec![]; let mut memories = Map::with_capacity(module.imported_memories.len()); @@ -478,7 +489,7 @@ fn import_memories( if link_errors.len() > 0 { Err(link_errors) } else { - Ok((vm_memories.into_boxed_map(), memories.into_boxed_map())) + Ok((memories.into_boxed_map(), vm_memories.into_boxed_map())) } } @@ -550,25 +561,28 @@ fn import_tables( fn import_globals( module: &ModuleInner, imports: &mut ImportObject, -) -> LinkResult> { +) -> LinkResult<( + BoxedMap, + BoxedMap, +)> { let mut link_errors = vec![]; let mut globals = Map::with_capacity(module.imported_globals.len()); + let mut vm_globals = Map::with_capacity(module.imported_globals.len()); for (_, (ImportName { namespace, name }, imported_global_desc)) in &module.imported_globals { let import = imports .get_namespace(namespace) .and_then(|namespace| namespace.get_export(name)); match import { - Some(Export::Global { local, desc }) => { - if desc == *imported_global_desc { - globals.push(vm::ImportedGlobal { - global: local.inner(), - }); + Some(Export::Global(mut global)) => { + if global.description() == *imported_global_desc { + vm_globals.push(global.vm_local_global()); + globals.push(global); } else { link_errors.push(LinkError::IncorrectGlobalDescription { namespace: namespace.clone(), name: name.clone(), - expected: imported_global_desc.clone(), - found: desc.clone(), + expected: *imported_global_desc, + found: global.description(), }); } } @@ -599,6 +613,6 @@ fn import_globals( if link_errors.len() > 0 { Err(link_errors) } else { - Ok(globals.into_boxed_map()) + Ok((globals.into_boxed_map(), vm_globals.into_boxed_map())) } } diff --git a/lib/runtime-core/src/export.rs b/lib/runtime-core/src/export.rs index 9a9feff42..894c445d5 100644 --- a/lib/runtime-core/src/export.rs +++ b/lib/runtime-core/src/export.rs @@ -1,9 +1,10 @@ use crate::{ + global::Global, instance::InstanceInner, memory::Memory, module::ExportIndex, module::ModuleInner, - types::{FuncSig, GlobalDesc, TableDesc}, + types::{FuncSig, TableDesc}, vm, }; use hashbrown::hash_map; @@ -27,10 +28,7 @@ pub enum Export { ctx: Context, desc: TableDesc, }, - Global { - local: GlobalPointer, - desc: GlobalDesc, - }, + Global(Global), } #[derive(Debug, Clone)] @@ -65,22 +63,6 @@ impl TablePointer { } } -#[derive(Debug, Clone)] -pub struct GlobalPointer(*mut vm::LocalGlobal); - -impl GlobalPointer { - /// This needs to be unsafe because there is - /// no way to check whether the passed function - /// is valid and has the right signature. - pub unsafe fn new(f: *mut vm::LocalGlobal) -> Self { - GlobalPointer(f) - } - - pub(crate) fn inner(&self) -> *mut vm::LocalGlobal { - self.0 - } -} - pub struct ExportIter<'a> { inner: &'a mut InstanceInner, iter: hash_map::Iter<'a, String, ExportIndex>, diff --git a/lib/runtime-core/src/global.rs b/lib/runtime-core/src/global.rs index c263499b5..9814b0ba6 100644 --- a/lib/runtime-core/src/global.rs +++ b/lib/runtime-core/src/global.rs @@ -1,8 +1,10 @@ use crate::{ + export::Export, + import::IsExport, types::{GlobalDesc, Type, Value}, vm, }; -use std::{cell::RefCell, rc::Rc}; +use std::{cell::RefCell, fmt, rc::Rc}; pub struct Global { desc: GlobalDesc, @@ -35,7 +37,7 @@ impl Global { Self { desc, - storage: Rc::new(RefCell::new(local_global)) + storage: Rc::new(RefCell::new(local_global)), } } @@ -79,6 +81,12 @@ impl Global { } } +impl IsExport for Global { + fn to_export(&mut self) -> Export { + Export::Global(self.clone()) + } +} + impl Clone for Global { fn clone(&self) -> Self { Self { @@ -86,4 +94,13 @@ impl Clone for Global { storage: Rc::clone(&self.storage), } } -} \ No newline at end of file +} + +impl fmt::Debug for Global { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Global") + .field("desc", &self.desc) + .field("value", &self.get()) + .finish() + } +} diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 271bc8a4d..cc2021096 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -2,17 +2,17 @@ use crate::{ backend::Token, backing::{ImportBacking, LocalBacking}, error::{CallError, CallResult, ResolveError, ResolveResult, Result}, - export::{Context, Export, ExportIter, FuncPointer, GlobalPointer, TablePointer}, + export::{Context, Export, ExportIter, FuncPointer, TablePointer}, + global::Global, import::{ImportObject, LikeNamespace}, memory::Memory, module::{ExportIndex, Module, ModuleInner}, types::{ - FuncIndex, FuncSig, GlobalDesc, GlobalIndex, LocalOrImport, MemoryIndex, TableDesc, - TableIndex, Value, + FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableDesc, TableIndex, Value, }, vm, }; -use std::{mem, rc::Rc}; +use std::{mem, sync::Arc}; pub(crate) struct InstanceInner { #[allow(dead_code)] @@ -29,14 +29,17 @@ pub(crate) struct InstanceInner { /// /// [`ImportObject`]: struct.ImportObject.html pub struct Instance { - module: Rc, + module: Arc, inner: Box, #[allow(dead_code)] imports: Box, } impl Instance { - pub(crate) fn new(module: Rc, mut imports: Box) -> Result { + pub(crate) fn new( + module: Arc, + mut imports: Box, + ) -> Result { // We need the backing and import_backing to create a vm::Ctx, but we need // a vm::Ctx to create a backing and an import_backing. The solution is to create an // uninitialized vm::Ctx and then initialize it in-place. @@ -182,7 +185,7 @@ impl Instance { /// The module used to instantiate this Instance. pub fn module(&self) -> Module { - Module::new(Rc::clone(&self.module)) + Module::new(Arc::clone(&self.module)) } } @@ -248,8 +251,8 @@ impl InstanceInner { Export::Memory(memory) } ExportIndex::Global(global_index) => { - let (local, desc) = self.get_global_from_index(module, *global_index); - Export::Global { local, desc } + let global = self.get_global_from_index(module, *global_index); + Export::Global(global) } ExportIndex::Table(table_index) => { let (local, ctx, desc) = self.get_table_from_index(module, *table_index); @@ -308,34 +311,13 @@ impl InstanceInner { } } - fn get_global_from_index( - &mut self, - module: &ModuleInner, - global_index: GlobalIndex, - ) -> (GlobalPointer, GlobalDesc) { + fn get_global_from_index(&mut self, module: &ModuleInner, global_index: GlobalIndex) -> Global { match global_index.local_or_import(module) { LocalOrImport::Local(local_global_index) => { - let vm_global = &mut self.backing.vm_globals[local_global_index]; - ( - unsafe { GlobalPointer::new(vm_global) }, - module - .globals - .get(local_global_index) - .expect("broken invariant, globals") - .desc, - ) + self.backing.globals[local_global_index].clone() } - LocalOrImport::Import(imported_global_index) => { - let &(_, imported_global_desc) = &module - .imported_globals - .get(imported_global_index) - .expect("missing imported global index"); - let vm::ImportedGlobal { global } = - &self.import_backing.vm_globals[imported_global_index]; - ( - unsafe { GlobalPointer::new(*global) }, - *imported_global_desc, - ) + LocalOrImport::Import(import_global_index) => { + self.import_backing.globals[import_global_index].clone() } } } diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 457922fed..713d94b7d 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -9,9 +9,9 @@ pub mod backend; mod backing; pub mod error; pub mod export; +pub mod global; pub mod import; pub mod instance; -pub mod global; pub mod memory; pub mod module; mod sig_registry; @@ -30,7 +30,7 @@ pub use self::error::Result; pub use self::instance::Instance; #[doc(inline)] pub use self::module::Module; -use std::rc::Rc; +use std::sync::Arc; pub mod prelude { pub use crate::import::{ImportObject, Namespace}; @@ -56,7 +56,7 @@ pub fn compile_with( let token = backend::Token::generate(); compiler .compile(wasm, token) - .map(|inner| module::Module::new(Rc::new(inner))) + .map(|inner| module::Module::new(Arc::new(inner))) } /// Perform validation as defined by the diff --git a/lib/runtime-core/src/memory/mod.rs b/lib/runtime-core/src/memory/mod.rs index 4d21a8431..f29ae1064 100644 --- a/lib/runtime-core/src/memory/mod.rs +++ b/lib/runtime-core/src/memory/mod.rs @@ -6,7 +6,7 @@ use crate::{ types::{MemoryDesc, ValueType}, vm, }; -use std::{cell::RefCell, fmt, mem, ptr, slice, rc::Rc}; +use std::{cell::RefCell, fmt, mem, ptr, rc::Rc, slice}; pub use self::dynamic::DynamicMemory; pub use self::static_::{SharedStaticMemory, StaticMemory}; @@ -52,8 +52,12 @@ impl Memory { pub fn grow(&mut self, delta: u32) -> Option { match &mut *self.storage.borrow_mut() { - (MemoryStorage::Dynamic(ref mut dynamic_memory), ref mut local) => dynamic_memory.grow(delta, local), - (MemoryStorage::Static(ref mut static_memory), ref mut local) => static_memory.grow(delta, local), + (MemoryStorage::Dynamic(ref mut dynamic_memory), ref mut local) => { + dynamic_memory.grow(delta, local) + } + (MemoryStorage::Static(ref mut static_memory), ref mut local) => { + static_memory.grow(delta, local) + } (MemoryStorage::SharedStatic(_), _) => unimplemented!(), } } @@ -81,9 +85,12 @@ impl Memory { let bytes_size = count * mem::size_of::(); if offset + bytes_size <= mem_slice.len() { - let buffer = &mem_slice[offset .. offset + bytes_size]; + let buffer = &mem_slice[offset..offset + bytes_size]; let value_type_buffer = unsafe { - slice::from_raw_parts(buffer.as_ptr() as *const T, buffer.len() / mem::size_of::()) + slice::from_raw_parts( + buffer.as_ptr() as *const T, + buffer.len() / mem::size_of::(), + ) }; Ok(value_type_buffer.to_vec()) } else { @@ -105,10 +112,9 @@ impl Memory { let bytes_size = values.len() * mem::size_of::(); if offset + bytes_size <= mem_slice.len() { - let u8_buffer = unsafe { - slice::from_raw_parts(values.as_ptr() as *const u8, bytes_size) - }; - mem_slice[offset .. offset + bytes_size].copy_from_slice(u8_buffer); + let u8_buffer = + unsafe { slice::from_raw_parts(values.as_ptr() as *const u8, bytes_size) }; + mem_slice[offset..offset + bytes_size].copy_from_slice(u8_buffer); Ok(()) } else { Err(()) @@ -129,7 +135,10 @@ impl Memory { }; let t_buffer = unsafe { - slice::from_raw_parts(mem_slice.as_ptr() as *const T, mem_slice.len() / mem::size_of::()) + slice::from_raw_parts( + mem_slice.as_ptr() as *const T, + mem_slice.len() / mem::size_of::(), + ) }; f(t_buffer) @@ -149,7 +158,10 @@ impl Memory { }; let t_buffer = unsafe { - slice::from_raw_parts_mut(mem_slice.as_mut_ptr() as *mut T, mem_slice.len() / mem::size_of::()) + slice::from_raw_parts_mut( + mem_slice.as_mut_ptr() as *mut T, + mem_slice.len() / mem::size_of::(), + ) }; f(t_buffer) diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index 618c3879e..e3c6021f8 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -5,14 +5,14 @@ use crate::{ sig_registry::SigRegistry, structures::Map, types::{ - FuncIndex, Global, GlobalDesc, GlobalIndex, ImportedFuncIndex, ImportedGlobalIndex, + FuncIndex, GlobalDesc, GlobalIndex, GlobalInit, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex, ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryDesc, MemoryIndex, SigIndex, TableDesc, TableIndex, }, Instance, }; use hashbrown::HashMap; -use std::rc::Rc; +use std::sync::Arc; /// This is used to instantiate a new WebAssembly module. #[doc(hidden)] @@ -22,7 +22,7 @@ pub struct ModuleInner { // This are strictly local and the typsystem ensures that. pub memories: Map, - pub globals: Map, + pub globals: Map, pub tables: Map, // These are strictly imported and the typesystem ensures that. @@ -49,10 +49,10 @@ pub struct ModuleInner { /// /// [`compile`]: fn.compile.html /// [`compile_with`]: fn.compile_with.html -pub struct Module(#[doc(hidden)] pub Rc); +pub struct Module(#[doc(hidden)] pub Arc); impl Module { - pub(crate) fn new(inner: Rc) -> Self { + pub(crate) fn new(inner: Arc) -> Self { Module(inner) } @@ -79,7 +79,7 @@ impl Module { /// # } /// ``` pub fn instantiate(&self, import_object: ImportObject) -> Result { - Instance::new(Rc::clone(&self.0), Box::new(import_object)) + Instance::new(Arc::clone(&self.0), Box::new(import_object)) } } diff --git a/lib/runtime-core/src/sys/unix/memory.rs b/lib/runtime-core/src/sys/unix/memory.rs index 6001bbfcf..097c7f5a7 100644 --- a/lib/runtime-core/src/sys/unix/memory.rs +++ b/lib/runtime-core/src/sys/unix/memory.rs @@ -4,6 +4,9 @@ use page_size; use std::ops::{Bound, RangeBounds}; use std::{ptr, slice}; +unsafe impl Send for Memory {} +unsafe impl Sync for Memory {} + #[derive(Debug)] pub struct Memory { ptr: *mut u8, diff --git a/lib/runtime-core/src/sys/windows/memory.rs b/lib/runtime-core/src/sys/windows/memory.rs index 5a2a243b4..13e6e0447 100644 --- a/lib/runtime-core/src/sys/windows/memory.rs +++ b/lib/runtime-core/src/sys/windows/memory.rs @@ -7,6 +7,9 @@ use page_size; use std::ops::{Bound, RangeBounds}; use std::{ptr, slice}; +unsafe impl Send for Memory {} +unsafe impl Sync for Memory {} + #[derive(Debug)] pub struct Memory { ptr: *mut u8, diff --git a/lib/runtime-core/src/types.rs b/lib/runtime-core/src/types.rs index 1defb8ef7..a6389d56f 100644 --- a/lib/runtime-core/src/types.rs +++ b/lib/runtime-core/src/types.rs @@ -71,7 +71,7 @@ pub enum ValueError { pub trait ValueType: Copy + Clone where - Self: Sized + Self: Sized, { fn into_le(self, buffer: &mut [u8]); fn from_le(buffer: &[u8]) -> Result; @@ -165,7 +165,7 @@ pub struct GlobalDesc { /// A wasm global. #[derive(Debug, Clone)] -pub struct Global { +pub struct GlobalInit { pub desc: GlobalDesc, pub init: Initializer, } diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index d8f9fe1d6..3a484fa37 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -19,7 +19,7 @@ pub struct Ctx { pub(crate) tables: *mut LocalTable, /// A pointer to an array of locally-defined globals, indexed by `GlobalIndex`. - pub(crate) globals: *mut LocalGlobal, + pub(crate) globals: *mut *mut LocalGlobal, /// A pointer to an array of imported memories, indexed by `MemoryIndex, pub(crate) imported_memories: *mut *mut LocalMemory, @@ -28,7 +28,7 @@ pub struct Ctx { pub(crate) imported_tables: *mut ImportedTable, /// A pointer to an array of imported globals, indexed by `GlobalIndex`. - pub(crate) imported_globals: *mut ImportedGlobal, + pub(crate) imported_globals: *mut *mut LocalGlobal, /// A pointer to an array of imported functions, indexed by `FuncIndex`. pub(crate) imported_funcs: *mut ImportedFunc, @@ -307,29 +307,6 @@ impl LocalMemory { } } -// #[derive(Debug, Clone)] -// #[repr(C)] -// pub struct ImportedMemory { -// /// A pointer to the memory definition. -// pub memory: *mut LocalMemory, -// pub vmctx: *mut Ctx, -// } - -// impl ImportedMemory { -// #[allow(clippy::erasing_op)] // TODO -// pub fn offset_memory() -> u8 { -// 0 * (mem::size_of::() as u8) -// } - -// pub fn offset_vmctx() -> u8 { -// 1 * (mem::size_of::() as u8) -// } - -// pub fn size() -> u8 { -// mem::size_of::() as u8 -// } -// } - /// Definition of a global used by the VM. #[derive(Debug, Clone)] #[repr(C)] @@ -352,23 +329,6 @@ impl LocalGlobal { } } -#[derive(Debug, Clone)] -#[repr(C)] -pub struct ImportedGlobal { - pub global: *mut LocalGlobal, -} - -impl ImportedGlobal { - #[allow(clippy::erasing_op)] // TODO - pub fn offset_global() -> u8 { - 0 * (mem::size_of::() as u8) - } - - pub fn size() -> u8 { - mem::size_of::() as u8 - } -} - #[derive(Debug, Clone, Copy)] #[repr(transparent)] pub struct SigId(pub u32); @@ -412,10 +372,7 @@ impl Anyfunc { #[cfg(test)] mod vm_offset_tests { - use super::{ - Anyfunc, Ctx, ImportedFunc, ImportedGlobal, ImportedTable, LocalGlobal, LocalMemory, - LocalTable, - }; + use super::{Anyfunc, Ctx, ImportedFunc, ImportedTable, LocalGlobal, LocalMemory, LocalTable}; #[test] fn vmctx() { @@ -515,14 +472,6 @@ mod vm_offset_tests { ); } - #[test] - fn imported_global() { - assert_eq!( - ImportedGlobal::offset_global() as usize, - offset_of!(ImportedGlobal => global).get_byte_offset(), - ); - } - #[test] fn cc_anyfunc() { assert_eq!( @@ -574,12 +523,15 @@ mod vm_ctx_tests { let mut local_backing = LocalBacking { memories: Map::new().into_boxed_map(), tables: Map::new().into_boxed_map(), + globals: Map::new().into_boxed_map(), + vm_memories: Map::new().into_boxed_map(), vm_tables: Map::new().into_boxed_map(), vm_globals: Map::new().into_boxed_map(), }; let mut import_backing = ImportBacking { memories: Map::new().into_boxed_map(), + globals: Map::new().into_boxed_map(), vm_functions: Map::new().into_boxed_map(), vm_memories: Map::new().into_boxed_map(),