mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-22 03:02:08 +00:00
user-functions initial
This commit is contained in:
@ -1,4 +1,6 @@
|
|||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use builder::module;
|
use builder::module;
|
||||||
use elements::{Module, FunctionType, ExportEntry, Internal, GlobalEntry, GlobalType,
|
use elements::{Module, FunctionType, ExportEntry, Internal, GlobalEntry, GlobalType,
|
||||||
ValueType, InitExpr, Opcode, Opcodes};
|
ValueType, InitExpr, Opcode, Opcodes};
|
||||||
@ -67,6 +69,19 @@ const INDEX_FUNC_MIN_NONUSED: u32 = 7;
|
|||||||
/// Max index of reserved function.
|
/// Max index of reserved function.
|
||||||
const INDEX_FUNC_MAX: u32 = 10000;
|
const INDEX_FUNC_MAX: u32 = 10000;
|
||||||
|
|
||||||
|
/// Set of user-defined functions
|
||||||
|
pub type UserFunctions = HashMap<String, UserFunction>;
|
||||||
|
|
||||||
|
/// User function closure
|
||||||
|
pub type UserFunctionClosure = Box<Fn(&CallerContext) -> Result<Option<RuntimeValue>, Error>>;
|
||||||
|
|
||||||
|
/// Signature of user-defined env function
|
||||||
|
pub struct UserFunction {
|
||||||
|
params: Vec<ValueType>,
|
||||||
|
result: Option<ValueType>,
|
||||||
|
closure: UserFunctionClosure,
|
||||||
|
}
|
||||||
|
|
||||||
/// Environment parameters.
|
/// Environment parameters.
|
||||||
pub struct EnvParams {
|
pub struct EnvParams {
|
||||||
/// Stack size in bytes.
|
/// Stack size in bytes.
|
||||||
@ -77,17 +92,21 @@ pub struct EnvParams {
|
|||||||
pub allow_memory_growth: bool,
|
pub allow_memory_growth: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserFunctionsInternals = HashMap<u32, UserFunctionClosure>;
|
||||||
|
|
||||||
pub struct EnvModuleInstance {
|
pub struct EnvModuleInstance {
|
||||||
_params: EnvParams,
|
_params: EnvParams,
|
||||||
|
user_functions: UserFunctionsInternals,
|
||||||
instance: ModuleInstance,
|
instance: ModuleInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EnvModuleInstance {
|
impl EnvModuleInstance {
|
||||||
pub fn new(params: EnvParams, module: Module) -> Result<Self, Error> {
|
pub fn new(params: EnvParams, user_functions: UserFunctionsInternals, module: Module) -> Result<Self, Error> {
|
||||||
let instance = ModuleInstance::new(Weak::default(), module)?;
|
let instance = ModuleInstance::new(Weak::default(), module)?;
|
||||||
|
|
||||||
Ok(EnvModuleInstance {
|
Ok(EnvModuleInstance {
|
||||||
_params: params,
|
_params: params,
|
||||||
|
user_functions: user_functions,
|
||||||
instance: instance,
|
instance: instance,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -157,12 +176,12 @@ impl ModuleInstanceInterface for EnvModuleInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn env_module() -> Result<EnvModuleInstance, Error> {
|
pub fn env_module(user_functions: UserFunctions) -> Result<EnvModuleInstance, Error> {
|
||||||
let env_params = EnvParams::default();
|
let mut env_params = EnvParams::default();
|
||||||
debug_assert!(env_params.total_stack < env_params.total_memory);
|
debug_assert!(env_params.total_stack < env_params.total_memory);
|
||||||
debug_assert!((env_params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0);
|
debug_assert!((env_params.total_stack % LINEAR_MEMORY_PAGE_SIZE) == 0);
|
||||||
debug_assert!((env_params.total_memory % LINEAR_MEMORY_PAGE_SIZE) == 0);
|
debug_assert!((env_params.total_memory % LINEAR_MEMORY_PAGE_SIZE) == 0);
|
||||||
let module = module()
|
let mut module = module()
|
||||||
// memory regions
|
// memory regions
|
||||||
.memory()
|
.memory()
|
||||||
.with_min(env_params.total_memory / LINEAR_MEMORY_PAGE_SIZE)
|
.with_min(env_params.total_memory / LINEAR_MEMORY_PAGE_SIZE)
|
||||||
@ -214,25 +233,32 @@ pub fn env_module() -> Result<EnvModuleInstance, Error> {
|
|||||||
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
||||||
.build()
|
.build()
|
||||||
.with_export(ExportEntry::new("getTotalMemory".into(), Internal::Function(INDEX_FUNC_GET_TOTAL_MEMORY)))
|
.with_export(ExportEntry::new("getTotalMemory".into(), Internal::Function(INDEX_FUNC_GET_TOTAL_MEMORY)))
|
||||||
// non-standard functions (TODO: pass as parameters to EnvModuleInstance)
|
|
||||||
.function()
|
|
||||||
.signature().param().i32().build()
|
|
||||||
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
|
||||||
.build()
|
|
||||||
.with_export(ExportEntry::new("gas".into(), Internal::Function(INDEX_FUNC_MAX + 1)))
|
|
||||||
.function()
|
|
||||||
.signature().return_type().i32().build()
|
|
||||||
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
|
||||||
.build()
|
|
||||||
.with_export(ExportEntry::new("_storage_size".into(), Internal::Function(INDEX_FUNC_MAX + 2)))
|
|
||||||
.function()
|
|
||||||
.signature().param().i32().param().i32().param().i32().return_type().i32().build()
|
|
||||||
.body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
|
||||||
.build()
|
|
||||||
.with_export(ExportEntry::new("_storage_write".into(), Internal::Function(INDEX_FUNC_MAX + 3)))
|
|
||||||
.build();
|
.build();
|
||||||
|
// non-standard functions (TODO: pass as parameters to EnvModuleInstance)
|
||||||
|
// .function()
|
||||||
|
// .signature().param().i32().build()
|
||||||
|
// .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
||||||
|
// .build()
|
||||||
|
// .with_export(ExportEntry::new("gas".into(), Internal::Function(INDEX_FUNC_MAX + 1)))
|
||||||
|
// .function()
|
||||||
|
// .signature().return_type().i32().build()
|
||||||
|
// .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
||||||
|
// .build()
|
||||||
|
// .with_export(ExportEntry::new("_storage_size".into(), Internal::Function(INDEX_FUNC_MAX + 2)))
|
||||||
|
// .function()
|
||||||
|
// .signature().param().i32().param().i32().param().i32().return_type().i32().build()
|
||||||
|
// .body().with_opcodes(Opcodes::new(vec![Opcode::Unreachable, Opcode::End])).build()
|
||||||
|
// .build()
|
||||||
|
// .with_export(ExportEntry::new("_storage_write".into(), Internal::Function(INDEX_FUNC_MAX + 3)))
|
||||||
|
// .build();
|
||||||
|
|
||||||
EnvModuleInstance::new(env_params, module)
|
let mut funcs = user_functions;
|
||||||
|
let internals = HashMap::new();
|
||||||
|
for (func_name, func) in funcs.drain() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EnvModuleInstance::new(env_params, internals, module)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for EnvParams {
|
impl Default for EnvParams {
|
||||||
|
@ -4,7 +4,7 @@ use std::collections::hash_map::Entry;
|
|||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use elements::Module;
|
use elements::Module;
|
||||||
use interpreter::Error;
|
use interpreter::Error;
|
||||||
use interpreter::env::env_module;
|
use interpreter::env::{self, env_module};
|
||||||
use interpreter::module::{ModuleInstance, ModuleInstanceInterface};
|
use interpreter::module::{ModuleInstance, ModuleInstanceInterface};
|
||||||
|
|
||||||
/// Program instance. Program is a set of instantiated modules.
|
/// Program instance. Program is a set of instantiated modules.
|
||||||
@ -27,6 +27,12 @@ impl ProgramInstance {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_functions(funcs: env::UserFunctions) -> Result<Self, Error> {
|
||||||
|
Ok(ProgramInstance {
|
||||||
|
essence: Arc::new(ProgramInstanceEssence::with_functions(funcs)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Instantiate module.
|
/// Instantiate module.
|
||||||
pub fn add_module(&self, name: &str, module: Module) -> Result<Arc<ModuleInstance>, Error> {
|
pub fn add_module(&self, name: &str, module: Module) -> Result<Arc<ModuleInstance>, Error> {
|
||||||
let module_instance = Arc::new(ModuleInstance::new(Arc::downgrade(&self.essence), module)?);
|
let module_instance = Arc::new(ModuleInstance::new(Arc::downgrade(&self.essence), module)?);
|
||||||
@ -49,8 +55,12 @@ impl ProgramInstance {
|
|||||||
impl ProgramInstanceEssence {
|
impl ProgramInstanceEssence {
|
||||||
/// Create new program essence.
|
/// Create new program essence.
|
||||||
pub fn new() -> Result<Self, Error> {
|
pub fn new() -> Result<Self, Error> {
|
||||||
|
ProgramInstanceEssence::with_functions(HashMap::with_capacity(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_functions(funcs: env::UserFunctions) -> Result<Self, Error> {
|
||||||
let mut modules = HashMap::new();
|
let mut modules = HashMap::new();
|
||||||
let env_module: Arc<ModuleInstanceInterface> = Arc::new(env_module()?);
|
let env_module: Arc<ModuleInstanceInterface> = Arc::new(env_module(funcs)?);
|
||||||
modules.insert("env".into(), env_module);
|
modules.insert("env".into(), env_module);
|
||||||
Ok(ProgramInstanceEssence {
|
Ok(ProgramInstanceEssence {
|
||||||
modules: RwLock::new(modules),
|
modules: RwLock::new(modules),
|
||||||
|
Reference in New Issue
Block a user