mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 08:10:49 +00:00
Add new global import api
This commit is contained in:
parent
1be20b19e7
commit
98305c8731
@ -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,
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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))
|
||||
"#;
|
||||
|
@ -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<Vec<Value>>;
|
||||
}
|
||||
|
||||
pub trait FuncResolver {
|
||||
pub trait FuncResolver: Send + Sync {
|
||||
/// This returns a pointer to the function designated by the `local_func_index`
|
||||
/// parameter.
|
||||
fn get(
|
||||
|
@ -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<LocalMemoryIndex, Memory>,
|
||||
pub(crate) tables: BoxedMap<LocalTableIndex, TableBacking>,
|
||||
pub(crate) globals: BoxedMap<LocalGlobalIndex, Global>,
|
||||
|
||||
pub(crate) vm_memories: BoxedMap<LocalMemoryIndex, *mut vm::LocalMemory>,
|
||||
pub(crate) vm_tables: BoxedMap<LocalTableIndex, vm::LocalTable>,
|
||||
pub(crate) vm_globals: BoxedMap<LocalGlobalIndex, vm::LocalGlobal>,
|
||||
pub(crate) vm_globals: BoxedMap<LocalGlobalIndex, *mut vm::LocalGlobal>,
|
||||
}
|
||||
|
||||
// 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<LocalGlobalIndex, vm::LocalGlobal> {
|
||||
fn generate_globals(
|
||||
module: &ModuleInner,
|
||||
imports: &ImportBacking,
|
||||
) -> BoxedMap<LocalGlobalIndex, Global> {
|
||||
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<LocalGlobalIndex, vm::LocalGlobal>,
|
||||
) -> BoxedMap<LocalGlobalIndex, vm::LocalGlobal> {
|
||||
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<LocalGlobalIndex, Global>,
|
||||
) -> BoxedMap<LocalGlobalIndex, *mut vm::LocalGlobal> {
|
||||
globals
|
||||
.iter_mut()
|
||||
.map(|(_, global)| global.vm_local_global())
|
||||
.collect::<Map<_, _>>()
|
||||
.into_boxed_map()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImportBacking {
|
||||
pub(crate) memories: BoxedMap<ImportedMemoryIndex, Memory>,
|
||||
pub(crate) globals: BoxedMap<ImportedGlobalIndex, Global>,
|
||||
|
||||
pub(crate) vm_functions: BoxedMap<ImportedFuncIndex, vm::ImportedFunc>,
|
||||
pub(crate) vm_memories: BoxedMap<ImportedMemoryIndex, *mut vm::LocalMemory>,
|
||||
pub(crate) vm_tables: BoxedMap<ImportedTableIndex, vm::ImportedTable>,
|
||||
pub(crate) vm_globals: BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>,
|
||||
pub(crate) vm_globals: BoxedMap<ImportedGlobalIndex, *mut vm::LocalGlobal>,
|
||||
}
|
||||
|
||||
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<ImportedMemoryIndex, *mut vm::LocalMemory>,
|
||||
BoxedMap<ImportedMemoryIndex, Memory>,
|
||||
BoxedMap<ImportedMemoryIndex, *mut vm::LocalMemory>,
|
||||
)> {
|
||||
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<BoxedMap<ImportedGlobalIndex, vm::ImportedGlobal>> {
|
||||
) -> LinkResult<(
|
||||
BoxedMap<ImportedGlobalIndex, Global>,
|
||||
BoxedMap<ImportedGlobalIndex, *mut vm::LocalGlobal>,
|
||||
)> {
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
@ -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>,
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
@ -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<ModuleInner>,
|
||||
module: Arc<ModuleInner>,
|
||||
inner: Box<InstanceInner>,
|
||||
#[allow(dead_code)]
|
||||
imports: Box<ImportObject>,
|
||||
}
|
||||
|
||||
impl Instance {
|
||||
pub(crate) fn new(module: Rc<ModuleInner>, mut imports: Box<ImportObject>) -> Result<Instance> {
|
||||
pub(crate) fn new(
|
||||
module: Arc<ModuleInner>,
|
||||
mut imports: Box<ImportObject>,
|
||||
) -> Result<Instance> {
|
||||
// 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<u32> {
|
||||
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::<T>();
|
||||
|
||||
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::<T>())
|
||||
slice::from_raw_parts(
|
||||
buffer.as_ptr() as *const T,
|
||||
buffer.len() / mem::size_of::<T>(),
|
||||
)
|
||||
};
|
||||
Ok(value_type_buffer.to_vec())
|
||||
} else {
|
||||
@ -105,10 +112,9 @@ impl Memory {
|
||||
let bytes_size = values.len() * mem::size_of::<T>();
|
||||
|
||||
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::<T>())
|
||||
slice::from_raw_parts(
|
||||
mem_slice.as_ptr() as *const T,
|
||||
mem_slice.len() / mem::size_of::<T>(),
|
||||
)
|
||||
};
|
||||
|
||||
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::<T>())
|
||||
slice::from_raw_parts_mut(
|
||||
mem_slice.as_mut_ptr() as *mut T,
|
||||
mem_slice.len() / mem::size_of::<T>(),
|
||||
)
|
||||
};
|
||||
|
||||
f(t_buffer)
|
||||
|
@ -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<LocalMemoryIndex, MemoryDesc>,
|
||||
pub globals: Map<LocalGlobalIndex, Global>,
|
||||
pub globals: Map<LocalGlobalIndex, GlobalInit>,
|
||||
pub tables: Map<LocalTableIndex, TableDesc>,
|
||||
|
||||
// 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<ModuleInner>);
|
||||
pub struct Module(#[doc(hidden)] pub Arc<ModuleInner>);
|
||||
|
||||
impl Module {
|
||||
pub(crate) fn new(inner: Rc<ModuleInner>) -> Self {
|
||||
pub(crate) fn new(inner: Arc<ModuleInner>) -> Self {
|
||||
Module(inner)
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ impl Module {
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn instantiate(&self, import_object: ImportObject) -> Result<Instance> {
|
||||
Instance::new(Rc::clone(&self.0), Box::new(import_object))
|
||||
Instance::new(Arc::clone(&self.0), Box::new(import_object))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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<Self, ValueError>;
|
||||
@ -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,
|
||||
}
|
||||
|
@ -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::<usize>() as u8)
|
||||
// }
|
||||
|
||||
// pub fn offset_vmctx() -> u8 {
|
||||
// 1 * (mem::size_of::<usize>() as u8)
|
||||
// }
|
||||
|
||||
// pub fn size() -> u8 {
|
||||
// mem::size_of::<Self>() 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::<usize>() as u8)
|
||||
}
|
||||
|
||||
pub fn size() -> u8 {
|
||||
mem::size_of::<Self>() 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(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user