mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-09 21:11:38 +00:00
Program import matching
This commit is contained in:
parent
02ad77f93c
commit
929d62b286
@ -1,64 +1,49 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use parking_lot::RwLock;
|
||||
use elements::Module;
|
||||
use interpreter::Error;
|
||||
use interpreter::module::{ModuleInstance, ModuleInstanceInterface};
|
||||
use interpreter::module::{ExecutionParams};
|
||||
use interpreter::store::{Store, ModuleId};
|
||||
|
||||
/// Program instance. Program is a set of instantiated modules.
|
||||
pub struct ProgramInstance {
|
||||
/// Shared data reference.
|
||||
essence: Arc<ProgramInstanceEssence>,
|
||||
}
|
||||
|
||||
/// Program instance essence.
|
||||
pub struct ProgramInstanceEssence {
|
||||
/// Loaded modules.
|
||||
modules: RwLock<HashMap<String, Arc<ModuleInstanceInterface>>>,
|
||||
store: Store,
|
||||
modules: HashMap<String, ModuleId>,
|
||||
}
|
||||
|
||||
impl ProgramInstance {
|
||||
/// Create new program instance.
|
||||
pub fn new() -> Self {
|
||||
ProgramInstance {
|
||||
essence: Arc::new(ProgramInstanceEssence::new()),
|
||||
store: Store::new(),
|
||||
modules: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Instantiate module with validation.
|
||||
pub fn add_module<'a>(&self, name: &str, module: Module, externals: Option<&'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>>) -> Result<Arc<ModuleInstance>, Error> {
|
||||
let mut module_instance = ModuleInstance::new(Arc::downgrade(&self.essence), name.into(), module)?;
|
||||
module_instance.instantiate(externals)?;
|
||||
pub fn add_module<'a>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
module: Module,
|
||||
start_exec_params: ExecutionParams,
|
||||
) -> Result<ModuleId, Error> {
|
||||
let extern_vals = Vec::new();
|
||||
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
|
||||
let module = self.modules[import_entry.module()];
|
||||
let extern_val = module
|
||||
.resolve_export(&self.store, import_entry.field())
|
||||
.ok_or_else(|| Error::Function(format!("Module {} doesn't have export {}", import_entry.module(), import_entry.field())))?;
|
||||
extern_vals.push(extern_val);
|
||||
}
|
||||
|
||||
let module_instance = Arc::new(module_instance);
|
||||
self.essence.modules.write().insert(name.into(), module_instance.clone());
|
||||
module_instance.run_start_function()?;
|
||||
Ok(module_instance)
|
||||
}
|
||||
let module_id = self.store.instantiate_module(&module, &extern_vals, start_exec_params)?;
|
||||
self.modules.insert(name.to_string(), module_id);
|
||||
|
||||
/// Insert instantiated module.
|
||||
pub fn insert_loaded_module(&self, name: &str, module_instance: Arc<ModuleInstanceInterface>) -> Result<Arc<ModuleInstanceInterface>, Error> {
|
||||
// replace existing module with the same name with new one
|
||||
self.essence.modules.write().insert(name.into(), Arc::clone(&module_instance));
|
||||
Ok(module_instance)
|
||||
Ok(module_id)
|
||||
}
|
||||
|
||||
/// Get one of the modules by name
|
||||
pub fn module(&self, name: &str) -> Option<Arc<ModuleInstanceInterface>> {
|
||||
self.essence.module(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl ProgramInstanceEssence {
|
||||
/// Create new program essence.
|
||||
pub fn new() -> Self {
|
||||
ProgramInstanceEssence {
|
||||
modules: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get module reference.
|
||||
pub fn module(&self, name: &str) -> Option<Arc<ModuleInstanceInterface>> {
|
||||
self.modules.read().get(name).cloned()
|
||||
pub fn module(&self, name: &str) -> Option<ModuleId> {
|
||||
self.modules.get(name).cloned()
|
||||
}
|
||||
}
|
||||
|
@ -983,7 +983,12 @@ impl<'store> Interpreter<'store> {
|
||||
}
|
||||
|
||||
impl<'a> FunctionContext<'a> {
|
||||
pub fn new(module: ModuleId, function: FuncId, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance>) -> Self {
|
||||
pub fn new(store: &Store, function: FuncId, externals: &'a HashMap<String, Arc<ModuleInstanceInterface + 'a>>, value_stack_limit: usize, frame_stack_limit: usize, function_type: &FunctionSignature, args: Vec<VariableInstance>) -> Self {
|
||||
let func_instance = function.resolve(store);
|
||||
let module = match *func_instance {
|
||||
FuncInstance::Defined { module, .. } => module,
|
||||
FuncInstance::Host { .. } => panic!("Host functions can't be called as internally defined functions; Thus FunctionContext can be created only with internally defined functions; qed"),
|
||||
};
|
||||
FunctionContext {
|
||||
is_initialized: false,
|
||||
function: function,
|
||||
|
@ -4,7 +4,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::collections::HashMap;
|
||||
use elements::{FunctionType, GlobalEntry, GlobalType, InitExpr, MemoryType, Module,
|
||||
Opcode, Opcodes, Local, TableType, Type};
|
||||
Opcode, Opcodes, Local, TableType, Type, Internal};
|
||||
use interpreter::{Error, RuntimeValue, MemoryInstance, TableInstance, ExecutionParams, CallerContext, FunctionSignature};
|
||||
use interpreter::runner::{FunctionContext, prepare_function_args, Interpreter};
|
||||
use validation::validate_module;
|
||||
@ -67,6 +67,14 @@ impl ModuleId {
|
||||
.get(idx as usize)
|
||||
.expect("Due to validation type should exists")
|
||||
}
|
||||
|
||||
pub fn resolve_export(&self, store: &Store, name: &str) -> Option<ExternVal> {
|
||||
let instance = store.resolve_module(*self);
|
||||
instance
|
||||
.exports
|
||||
.get(name)
|
||||
.cloned()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
@ -102,6 +110,7 @@ impl MemoryId {
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct GlobalId(u32);
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum ExternVal {
|
||||
Func(FuncId),
|
||||
Table(TableId),
|
||||
@ -167,7 +176,7 @@ struct ModuleInstance {
|
||||
tables: Vec<TableId>,
|
||||
memories: Vec<MemoryId>,
|
||||
globals: Vec<GlobalId>,
|
||||
exports: Vec<ExportInstance>,
|
||||
exports: HashMap<String, ExternVal>,
|
||||
}
|
||||
|
||||
impl ModuleInstance {
|
||||
@ -191,7 +200,7 @@ pub struct Store {
|
||||
}
|
||||
|
||||
impl Store {
|
||||
fn new() -> Store {
|
||||
pub fn new() -> Store {
|
||||
Store::default()
|
||||
}
|
||||
|
||||
@ -328,15 +337,38 @@ impl Store {
|
||||
instance.globals.push(global_id);
|
||||
}
|
||||
|
||||
for export in module.export_section().map(|es| es.entries()).unwrap_or(&[]) {
|
||||
let field = export.field();
|
||||
let extern_val: ExternVal = match *export.internal() {
|
||||
Internal::Function(idx) => {
|
||||
let func_id = instance.funcs.get(idx as usize).expect("Due to validation func should exists");
|
||||
ExternVal::Func(*func_id)
|
||||
},
|
||||
Internal::Global(idx) => {
|
||||
let global_id = instance.globals.get(idx as usize).expect("Due to validation global should exists");
|
||||
ExternVal::Global(*global_id)
|
||||
}
|
||||
Internal::Memory(idx) => {
|
||||
let memory_id = instance.memories.get(idx as usize).expect("Due to validation memory should exists");
|
||||
ExternVal::Memory(*memory_id)
|
||||
}
|
||||
Internal::Table(idx) => {
|
||||
let table_id = instance.tables.get(idx as usize).expect("Due to validation table should exists");
|
||||
ExternVal::Table(*table_id)
|
||||
}
|
||||
};
|
||||
instance.exports.insert(field.into(), extern_val);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn instantiate_module(
|
||||
pub fn instantiate_module(
|
||||
&mut self,
|
||||
module: &Module,
|
||||
extern_vals: &[ExternVal],
|
||||
start_exec_params: ExecutionParams,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<ModuleId, Error> {
|
||||
let mut instance = ModuleInstance::new();
|
||||
// Reserve the index of the module, but not yet push the module.
|
||||
let module_id = ModuleId((self.modules.len()) as u32);
|
||||
@ -404,7 +436,7 @@ impl Store {
|
||||
self.invoke(start_func, start_exec_params)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(module_id)
|
||||
}
|
||||
|
||||
fn invoke(&mut self, func: FuncId, params: ExecutionParams) -> Result<Option<RuntimeValue>, Error> {
|
||||
@ -414,7 +446,7 @@ impl Store {
|
||||
let func_type = func.resolve(self).func_type().resolve(self);
|
||||
let func_signature = FunctionSignature::Module(func_type);
|
||||
let args = prepare_function_args(&func_signature, outer.value_stack)?;
|
||||
let inner = FunctionContext::new(func, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &func_signature, args);
|
||||
let inner = FunctionContext::new(self, func, outer.externals, outer.value_stack_limit, outer.frame_stack_limit, &func_signature, args);
|
||||
let interpreter = Interpreter::new(self);
|
||||
interpreter.run_function(inner)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user