mirror of
https://github.com/fluencelabs/wasmer
synced 2025-03-16 16:20:49 +00:00
Add support for tables
This commit is contained in:
parent
20342c74b9
commit
74f0ff444a
@ -1,11 +1,6 @@
|
||||
use crate::runtime::{module::Module, vm};
|
||||
use std::ptr::NonNull;
|
||||
use crate::runtime::module::Module;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait Compiler {
|
||||
fn compile(&self, wasm: &[u8]) -> Result<Arc<Module>, String>;
|
||||
}
|
||||
|
||||
pub trait FuncResolver {
|
||||
fn resolve(&self, module: &Module, name: &str) -> Option<NonNull<vm::Func>>;
|
||||
}
|
||||
|
@ -2,7 +2,8 @@ use crate::runtime::{
|
||||
instance::{Import, Imports},
|
||||
memory::LinearMemory,
|
||||
module::{ImportName, Module},
|
||||
table::TableBacking,
|
||||
sig_registry::SigRegistry,
|
||||
table::{TableBacking, TableElements},
|
||||
types::{GlobalInit, MapIndex, Val},
|
||||
vm,
|
||||
};
|
||||
@ -18,13 +19,13 @@ pub struct LocalBacking {
|
||||
}
|
||||
|
||||
impl LocalBacking {
|
||||
pub fn new(module: &Module, imports: &ImportBacking) -> Self {
|
||||
pub fn new(module: &Module, imports: &ImportBacking, sig_registry: &SigRegistry) -> Self {
|
||||
let mut memories = Self::generate_memories(module);
|
||||
let mut tables = Self::generate_tables(module);
|
||||
let globals = Self::generate_globals(module);
|
||||
|
||||
let vm_memories = Self::finalize_memories(module, &mut memories[..]);
|
||||
let vm_tables = Self::finalize_tables(module, &mut tables[..]);
|
||||
let vm_tables = Self::finalize_tables(module, imports, &mut tables[..], sig_registry);
|
||||
let vm_globals = Self::finalize_globals(module, imports, globals);
|
||||
|
||||
Self {
|
||||
@ -60,7 +61,7 @@ impl LocalBacking {
|
||||
|
||||
fn finalize_memories(module: &Module, memories: &mut [LinearMemory]) -> Box<[vm::LocalMemory]> {
|
||||
for init in &module.data_initializers {
|
||||
assert!(init.base.is_none(), "globalvar base not supported yet");
|
||||
assert!(init.base.is_none(), "global base not supported yet");
|
||||
assert!(
|
||||
init.offset + init.data.len() <= memories[init.memory_index.index()].current_size()
|
||||
);
|
||||
@ -94,8 +95,40 @@ impl LocalBacking {
|
||||
tables.into_boxed_slice()
|
||||
}
|
||||
|
||||
// TODO: Actually finish this
|
||||
fn finalize_tables(_module: &Module, tables: &mut [TableBacking]) -> Box<[vm::LocalTable]> {
|
||||
fn finalize_tables(
|
||||
module: &Module,
|
||||
imports: &ImportBacking,
|
||||
tables: &mut [TableBacking],
|
||||
sig_registry: &SigRegistry,
|
||||
) -> Box<[vm::LocalTable]> {
|
||||
for init in &module.table_initializers {
|
||||
assert!(init.base.is_none(), "global base not supported yet");
|
||||
let table = &mut tables[init.table_index.index()];
|
||||
match table.elements {
|
||||
TableElements::Anyfunc(ref mut elements) => {
|
||||
for (i, &func_index) in init.elements.iter().enumerate() {
|
||||
let sig_index = module.signature_assoc[func_index];
|
||||
let vm_sig_id = sig_registry.get_vm_id(sig_index);
|
||||
|
||||
let func_data = if module.is_imported_function(func_index) {
|
||||
imports.functions[func_index.index()].clone()
|
||||
} else {
|
||||
vm::ImportedFunc {
|
||||
func: (module.function_resolver)(module, func_index)
|
||||
.unwrap()
|
||||
.as_ptr(),
|
||||
}
|
||||
};
|
||||
|
||||
elements[init.offset + i] = vm::Anyfunc {
|
||||
func_data,
|
||||
sig_id: vm_sig_id,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tables
|
||||
.iter_mut()
|
||||
.map(|table| table.into_vm_table())
|
||||
@ -103,9 +136,8 @@ impl LocalBacking {
|
||||
.into_boxed_slice()
|
||||
}
|
||||
|
||||
// TODO: Actually finish this
|
||||
fn generate_globals(module: &Module) -> Box<[vm::LocalGlobal]> {
|
||||
let mut globals = vec![vm::LocalGlobal::null(); module.globals.len()];
|
||||
let globals = vec![vm::LocalGlobal::null(); module.globals.len()];
|
||||
|
||||
globals.into_boxed_slice()
|
||||
}
|
||||
|
@ -22,10 +22,10 @@ pub struct Instance {
|
||||
|
||||
impl Instance {
|
||||
pub fn new(module: Arc<Module>, imports: &Imports) -> Result<Box<Instance>, String> {
|
||||
let import_backing = ImportBacking::new(&*module, imports)?;
|
||||
let backing = LocalBacking::new(&*module, &import_backing);
|
||||
let sig_registry = SigRegistry::new(&*module);
|
||||
|
||||
let sig_registry = SigRegistry::new();
|
||||
let import_backing = ImportBacking::new(&*module, imports)?;
|
||||
let backing = LocalBacking::new(&*module, &import_backing, &sig_registry);
|
||||
|
||||
Ok(Box::new(Instance {
|
||||
backing,
|
||||
@ -90,9 +90,7 @@ impl Instance {
|
||||
.collect();
|
||||
|
||||
let func_ptr = CodePtr::from_ptr(
|
||||
self.module
|
||||
.functions
|
||||
.resolve(&*self.module, name)
|
||||
(self.module.function_resolver)(&*self.module, func_index)
|
||||
.expect("broken invariant, func resolver not synced with module.exports")
|
||||
.cast()
|
||||
.as_ptr(),
|
||||
|
@ -8,7 +8,7 @@ mod table;
|
||||
pub mod types;
|
||||
pub mod vm;
|
||||
|
||||
pub use self::backend::{Compiler, FuncResolver};
|
||||
pub use self::backend::Compiler;
|
||||
pub use self::instance::{Import, Imports, Instance};
|
||||
pub use self::module::Module;
|
||||
|
||||
|
@ -1,13 +1,16 @@
|
||||
use crate::runtime::backend::FuncResolver;
|
||||
use crate::runtime::types::{
|
||||
FuncIndex, FuncSig, Global, GlobalDesc, GlobalIndex, Map, Memory, MemoryIndex, SigIndex, Table,
|
||||
TableIndex,
|
||||
use crate::runtime::{
|
||||
types::{
|
||||
FuncIndex, FuncSig, Global, GlobalDesc, GlobalIndex, Map, MapIndex, Memory, MemoryIndex,
|
||||
SigIndex, Table, TableIndex,
|
||||
},
|
||||
vm,
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use std::ptr::NonNull;
|
||||
|
||||
/// This is used to instantiate a new webassembly module.
|
||||
pub struct Module {
|
||||
pub functions: Box<dyn FuncResolver>,
|
||||
pub function_resolver: Box<dyn Fn(&Module, FuncIndex) -> Option<NonNull<vm::Func>>>,
|
||||
pub memories: Map<Memory, MemoryIndex>,
|
||||
pub globals: Map<Global, GlobalIndex>,
|
||||
pub tables: Map<Table, TableIndex>,
|
||||
@ -20,12 +23,19 @@ pub struct Module {
|
||||
pub exports: HashMap<String, Export>,
|
||||
|
||||
pub data_initializers: Vec<DataInitializer>,
|
||||
pub table_initializers: Vec<TableInitializer>,
|
||||
pub start_func: FuncIndex,
|
||||
|
||||
pub signature_assoc: Map<SigIndex, FuncIndex>,
|
||||
pub signatures: Map<FuncSig, SigIndex>,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub(in crate::runtime) fn is_imported_function(&self, func_index: FuncIndex) -> bool {
|
||||
func_index.index() < self.imported_functions.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ImportName {
|
||||
pub module: String,
|
||||
@ -52,3 +62,16 @@ pub struct DataInitializer {
|
||||
/// The initialization data.
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
/// A WebAssembly table initializer.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TableInitializer {
|
||||
/// The index of a table to initialize.
|
||||
pub table_index: TableIndex,
|
||||
/// Optionally, a global variable giving a base index.
|
||||
pub base: Option<GlobalIndex>,
|
||||
/// The offset to add to the base.
|
||||
pub offset: usize,
|
||||
/// The values to write into the table elements.
|
||||
pub elements: Vec<FuncIndex>,
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::runtime::{
|
||||
module::Module,
|
||||
types::{FuncSig, Map, SigIndex},
|
||||
vm,
|
||||
};
|
||||
@ -10,23 +11,34 @@ pub struct SigRegistry {
|
||||
}
|
||||
|
||||
impl SigRegistry {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
pub fn new(module: &Module) -> Self {
|
||||
let mut registry = Self {
|
||||
sig_set: HashMap::new(),
|
||||
signatures: Map::new(),
|
||||
};
|
||||
|
||||
for (_, &sig_index) in &module.signature_assoc {
|
||||
let func_sig = module.signatures[sig_index].clone();
|
||||
registry.register(func_sig);
|
||||
}
|
||||
|
||||
registry
|
||||
}
|
||||
|
||||
pub fn into_vm_signatures(&self) -> *const vm::SigId {
|
||||
self.signatures.as_ptr()
|
||||
}
|
||||
|
||||
pub fn register(&mut self, signature: FuncSig) {
|
||||
pub fn get_vm_id(&self, sig_index: SigIndex) -> vm::SigId {
|
||||
self.signatures[sig_index]
|
||||
}
|
||||
|
||||
fn register(&mut self, signature: FuncSig) {
|
||||
let index = self.sig_set.len();
|
||||
let vm_sig_id = self
|
||||
let vm_sig_id = *self
|
||||
.sig_set
|
||||
.entry(signature)
|
||||
.or_insert_with(|| vm::SigId(index as u32));
|
||||
self.signatures.push(*vm_sig_id);
|
||||
self.signatures.push(vm_sig_id);
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ impl Memory {
|
||||
}
|
||||
|
||||
/// A wasm func.
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct FuncSig {
|
||||
pub params: Vec<Type>,
|
||||
pub returns: Vec<Type>,
|
||||
|
Loading…
x
Reference in New Issue
Block a user