mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-05-24 13:11:34 +00:00
static variants of passed functions
This commit is contained in:
parent
9c2061c63c
commit
f2ee624cea
@ -1,5 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::borrow::Cow;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use elements::{FunctionType, Internal, ValueType};
|
use elements::{FunctionType, Internal, ValueType};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
@ -22,20 +23,62 @@ pub trait UserFunctionExecutor {
|
|||||||
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
|
fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum UserFunctionDescriptor {
|
||||||
|
Static(&'static str, &'static [ValueType]),
|
||||||
|
Heap(String, Vec<ValueType>),
|
||||||
|
}
|
||||||
|
|
||||||
/// User function type.
|
/// User function type.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct UserFunction {
|
pub struct UserFunction {
|
||||||
/// User function name.
|
pub desc: UserFunctionDescriptor,
|
||||||
pub name: String,
|
|
||||||
/// User function parameters (for signature matching).
|
|
||||||
pub params: Vec<ValueType>,
|
|
||||||
/// User function return type (for signature matching).
|
|
||||||
pub result: Option<ValueType>,
|
pub result: Option<ValueType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl UserFunction {
|
||||||
|
/// New function with statically known params
|
||||||
|
pub fn statik(name: &'static str, params: &'static [ValueType], result: Option<ValueType>) -> Self {
|
||||||
|
UserFunction {
|
||||||
|
desc: UserFunctionDescriptor::Static(name, params),
|
||||||
|
result: result,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// New function with statically unknown params
|
||||||
|
pub fn heap(name: String, params: Vec<ValueType>, result: Option<ValueType>) -> Self {
|
||||||
|
UserFunction {
|
||||||
|
desc: UserFunctionDescriptor::Heap(name, params),
|
||||||
|
result: result,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Name of the function
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
match self.desc {
|
||||||
|
UserFunctionDescriptor::Static(name, _) => name,
|
||||||
|
UserFunctionDescriptor::Heap(ref name, _) => name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Arguments of the function
|
||||||
|
pub fn params(&self) -> &[ValueType] {
|
||||||
|
match self.desc {
|
||||||
|
UserFunctionDescriptor::Static(_, params) => params,
|
||||||
|
UserFunctionDescriptor::Heap(_, ref params) => params,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return type of the function
|
||||||
|
pub fn result(&self) -> Option<ValueType> {
|
||||||
|
self.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set of user-defined functions
|
/// Set of user-defined functions
|
||||||
pub struct UserFunctions<'a> {
|
pub struct UserFunctions<'a> {
|
||||||
/// Functions list.
|
/// Functions list.
|
||||||
pub functions: Vec<UserFunction>,
|
pub functions: Cow<'static, [UserFunction]>,
|
||||||
/// Functions executor.
|
/// Functions executor.
|
||||||
pub executor: &'a mut UserFunctionExecutor,
|
pub executor: &'a mut UserFunctionExecutor,
|
||||||
}
|
}
|
||||||
@ -49,7 +92,7 @@ pub struct NativeModuleInstance<'a> {
|
|||||||
/// By-name functions index.
|
/// By-name functions index.
|
||||||
by_name: HashMap<String, u32>,
|
by_name: HashMap<String, u32>,
|
||||||
/// User functions list.
|
/// User functions list.
|
||||||
functions: Vec<UserFunction>,
|
functions: Cow<'static, [UserFunction]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NativeModuleInstance<'a> {
|
impl<'a> NativeModuleInstance<'a> {
|
||||||
@ -58,7 +101,7 @@ impl<'a> NativeModuleInstance<'a> {
|
|||||||
Ok(NativeModuleInstance {
|
Ok(NativeModuleInstance {
|
||||||
env: env,
|
env: env,
|
||||||
executor: RwLock::new(functions.executor),
|
executor: RwLock::new(functions.executor),
|
||||||
by_name: functions.functions.iter().enumerate().map(|(i, f)| (f.name.clone(), i as u32)).collect(),
|
by_name: functions.functions.iter().enumerate().map(|(i, f)| (f.name().to_owned(), i as u32)).collect(),
|
||||||
functions: functions.functions,
|
functions: functions.functions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -98,7 +141,7 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
|
|||||||
self.functions
|
self.functions
|
||||||
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
|
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
|
||||||
.ok_or(Error::Native(format!("missing native env function with index {}", index)))
|
.ok_or(Error::Native(format!("missing native env function with index {}", index)))
|
||||||
.map(|f| FunctionType::new(f.params.clone(), f.result.clone()))
|
.map(|f| FunctionType::new(f.params().to_vec(), f.result().clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
|
fn table(&self, index: ItemIndex) -> Result<Arc<TableInstance>, Error> {
|
||||||
@ -130,7 +173,7 @@ impl<'a> ModuleInstanceInterface for NativeModuleInstance<'a> {
|
|||||||
self.functions
|
self.functions
|
||||||
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
|
.get((index - NATIVE_INDEX_FUNC_MIN) as usize)
|
||||||
.ok_or(Error::Native(format!("trying to call native function with index {}", index)))
|
.ok_or(Error::Native(format!("trying to call native function with index {}", index)))
|
||||||
.and_then(|f| self.executor.write().execute(&f.name, outer))
|
.and_then(|f| self.executor.write().execute(&f.name(), outer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use builder::module;
|
|||||||
use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType,
|
use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType,
|
||||||
InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType};
|
InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType};
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::env_native::{env_native_module, UserFunction, UserFunctions, UserFunctionExecutor};
|
use interpreter::env_native::{env_native_module, UserFunction, UserFunctions, UserFunctionExecutor, UserFunctionDescriptor};
|
||||||
use interpreter::imports::ModuleImports;
|
use interpreter::imports::ModuleImports;
|
||||||
use interpreter::memory::MemoryInstance;
|
use interpreter::memory::MemoryInstance;
|
||||||
use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams};
|
use interpreter::module::{ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams};
|
||||||
@ -123,6 +123,25 @@ fn global_get_set() {
|
|||||||
assert_eq!(module.execute_index(2, vec![].into()).unwrap_err(), Error::Variable("trying to update variable of type I32 with value of type Some(I64)".into()));
|
assert_eq!(module.execute_index(2, vec![].into()).unwrap_err(), Error::Variable("trying to update variable of type I32 with value of type Some(I64)".into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SIGNATURE_I32: &'static [ValueType] = &[ValueType::I32];
|
||||||
|
|
||||||
|
const SIGNATURES: &'static [UserFunction] = &[
|
||||||
|
UserFunction {
|
||||||
|
desc: UserFunctionDescriptor::Static(
|
||||||
|
"add",
|
||||||
|
SIGNATURE_I32,
|
||||||
|
),
|
||||||
|
result: Some(ValueType::I32),
|
||||||
|
},
|
||||||
|
UserFunction {
|
||||||
|
desc: UserFunctionDescriptor::Static(
|
||||||
|
"sub",
|
||||||
|
SIGNATURE_I32,
|
||||||
|
),
|
||||||
|
result: Some(ValueType::I32),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_program_different_modules() {
|
fn single_program_different_modules() {
|
||||||
// user function executor
|
// user function executor
|
||||||
@ -170,15 +189,7 @@ fn single_program_different_modules() {
|
|||||||
{
|
{
|
||||||
let functions: UserFunctions = UserFunctions {
|
let functions: UserFunctions = UserFunctions {
|
||||||
executor: &mut executor,
|
executor: &mut executor,
|
||||||
functions: vec![UserFunction {
|
functions: ::std::borrow::Cow::from(SIGNATURES),
|
||||||
name: "add".into(),
|
|
||||||
params: vec![ValueType::I32],
|
|
||||||
result: Some(ValueType::I32),
|
|
||||||
}, UserFunction {
|
|
||||||
name: "sub".into(),
|
|
||||||
params: vec![ValueType::I32],
|
|
||||||
result: Some(ValueType::I32),
|
|
||||||
}],
|
|
||||||
};
|
};
|
||||||
let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
|
let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
|
||||||
let params = ExecutionParams::with_external("env".into(), native_env_instance);
|
let params = ExecutionParams::with_external("env".into(), native_env_instance);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user