mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-06-08 20:41:35 +00:00
fmt
This commit is contained in:
parent
92597ae56a
commit
f3584dbd17
@ -3,13 +3,12 @@ use std::cell::{Cell, RefCell};
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use elements::{FunctionType, GlobalType, InitExpr, Internal, External, Local, MemoryType,
|
use elements::{External, FunctionType, GlobalType, InitExpr, Internal, Local, MemoryType, Module,
|
||||||
Module, Opcode, Opcodes, TableType, Type, ResizableLimits};
|
Opcode, Opcodes, ResizableLimits, TableType, Type};
|
||||||
use interpreter::{Error, MemoryInstance,
|
use interpreter::{Error, MemoryInstance, RuntimeValue, TableInstance};
|
||||||
RuntimeValue, TableInstance};
|
|
||||||
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
|
use interpreter::runner::{prepare_function_args, FunctionContext, Interpreter};
|
||||||
use interpreter::host::AnyFunc;
|
use interpreter::host::AnyFunc;
|
||||||
use interpreter::imports::{Imports, ImportResolver};
|
use interpreter::imports::{ImportResolver, Imports};
|
||||||
use validation::validate_module;
|
use validation::validate_module;
|
||||||
use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX,
|
use common::{DEFAULT_FRAME_STACK_LIMIT, DEFAULT_MEMORY_INDEX, DEFAULT_TABLE_INDEX,
|
||||||
DEFAULT_VALUE_STACK_LIMIT};
|
DEFAULT_VALUE_STACK_LIMIT};
|
||||||
@ -69,9 +68,16 @@ pub enum FuncInstance {
|
|||||||
impl fmt::Debug for FuncInstance {
|
impl fmt::Debug for FuncInstance {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
&FuncInstance::Internal { ref func_type, ref module, .. } => {
|
&FuncInstance::Internal {
|
||||||
write!(f, "Internal {{ type={:?}, module={:?} }}", func_type, module)
|
ref func_type,
|
||||||
},
|
ref module,
|
||||||
|
..
|
||||||
|
} => write!(
|
||||||
|
f,
|
||||||
|
"Internal {{ type={:?}, module={:?} }}",
|
||||||
|
func_type,
|
||||||
|
module
|
||||||
|
),
|
||||||
&FuncInstance::Host { ref func_type, .. } => {
|
&FuncInstance::Host { ref func_type, .. } => {
|
||||||
write!(f, "Host {{ type={:?} }}", func_type)
|
write!(f, "Host {{ type={:?} }}", func_type)
|
||||||
}
|
}
|
||||||
@ -82,9 +88,8 @@ impl fmt::Debug for FuncInstance {
|
|||||||
impl FuncInstance {
|
impl FuncInstance {
|
||||||
pub fn func_type(&self) -> Rc<FunctionType> {
|
pub fn func_type(&self) -> Rc<FunctionType> {
|
||||||
match *self {
|
match *self {
|
||||||
FuncInstance::Internal { ref func_type, .. } | FuncInstance::Host { ref func_type, .. } => {
|
FuncInstance::Internal { ref func_type, .. } |
|
||||||
Rc::clone(func_type)
|
FuncInstance::Host { ref func_type, .. } => Rc::clone(func_type),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +125,9 @@ impl FuncInstance {
|
|||||||
);
|
);
|
||||||
InvokeKind::Internal(context)
|
InvokeKind::Internal(context)
|
||||||
}
|
}
|
||||||
FuncInstance::Host { ref host_func, .. } => InvokeKind::Host(Rc::clone(host_func), args),
|
FuncInstance::Host { ref host_func, .. } => {
|
||||||
|
InvokeKind::Host(Rc::clone(host_func), args)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
@ -128,9 +135,7 @@ impl FuncInstance {
|
|||||||
let mut interpreter = Interpreter::new(state);
|
let mut interpreter = Interpreter::new(state);
|
||||||
interpreter.run_function(ctx)
|
interpreter.run_function(ctx)
|
||||||
}
|
}
|
||||||
InvokeKind::Host(host_func, args) => {
|
InvokeKind::Host(host_func, args) => host_func.call_as_any(state as &mut Any, &args),
|
||||||
host_func.call_as_any(state as &mut Any, &args)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,7 +157,7 @@ impl GlobalInstance {
|
|||||||
pub fn new(val: RuntimeValue, mutable: bool) -> GlobalInstance {
|
pub fn new(val: RuntimeValue, mutable: bool) -> GlobalInstance {
|
||||||
GlobalInstance {
|
GlobalInstance {
|
||||||
val: Cell::new(val),
|
val: Cell::new(val),
|
||||||
mutable
|
mutable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,56 +192,33 @@ impl ModuleInstance {
|
|||||||
|
|
||||||
pub fn with_exports(exports: HashMap<String, ExternVal>) -> ModuleInstance {
|
pub fn with_exports(exports: HashMap<String, ExternVal>) -> ModuleInstance {
|
||||||
ModuleInstance {
|
ModuleInstance {
|
||||||
exports: RefCell::new(exports), ..Default::default()
|
exports: RefCell::new(exports),
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn memory_by_index(&self, idx: u32) -> Option<Rc<MemoryInstance>> {
|
pub fn memory_by_index(&self, idx: u32) -> Option<Rc<MemoryInstance>> {
|
||||||
self
|
self.memories.borrow().get(idx as usize).cloned()
|
||||||
.memories
|
|
||||||
.borrow()
|
|
||||||
.get(idx as usize)
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn table_by_index(&self, idx: u32) -> Option<Rc<TableInstance>> {
|
pub fn table_by_index(&self, idx: u32) -> Option<Rc<TableInstance>> {
|
||||||
self
|
self.tables.borrow().get(idx as usize).cloned()
|
||||||
.tables
|
|
||||||
.borrow()
|
|
||||||
.get(idx as usize)
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global_by_index(&self, idx: u32) -> Option<Rc<GlobalInstance>> {
|
pub fn global_by_index(&self, idx: u32) -> Option<Rc<GlobalInstance>> {
|
||||||
self
|
self.globals.borrow().get(idx as usize).cloned()
|
||||||
.globals
|
|
||||||
.borrow()
|
|
||||||
.get(idx as usize)
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn func_by_index(&self, idx: u32) -> Option<Rc<FuncInstance>> {
|
pub fn func_by_index(&self, idx: u32) -> Option<Rc<FuncInstance>> {
|
||||||
self
|
self.funcs.borrow().get(idx as usize).cloned()
|
||||||
.funcs
|
|
||||||
.borrow()
|
|
||||||
.get(idx as usize)
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn type_by_index(&self, idx: u32) -> Option<Rc<FunctionType>> {
|
pub fn type_by_index(&self, idx: u32) -> Option<Rc<FunctionType>> {
|
||||||
self
|
self.types.borrow().get(idx as usize).cloned()
|
||||||
.types
|
|
||||||
.borrow()
|
|
||||||
.get(idx as usize)
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> {
|
pub fn export_by_name(&self, name: &str) -> Option<ExternVal> {
|
||||||
self
|
self.exports.borrow().get(name).cloned()
|
||||||
.exports
|
|
||||||
.borrow()
|
|
||||||
.get(name)
|
|
||||||
.cloned()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_func(&self, func: Rc<FuncInstance>) {
|
fn push_func(&self, func: Rc<FuncInstance>) {
|
||||||
@ -260,10 +242,7 @@ impl ModuleInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal) {
|
fn insert_export<N: Into<String>>(&self, name: N, extern_val: ExternVal) {
|
||||||
self
|
self.exports.borrow_mut().insert(name.into(), extern_val);
|
||||||
.exports
|
|
||||||
.borrow_mut()
|
|
||||||
.insert(name.into(), extern_val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_module_internal(
|
fn alloc_module_internal(
|
||||||
@ -273,26 +252,29 @@ impl ModuleInstance {
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut aux_data = validate_module(module)?;
|
let mut aux_data = validate_module(module)?;
|
||||||
|
|
||||||
for &Type::Function(ref ty) in module
|
for &Type::Function(ref ty) in module.type_section().map(|ts| ts.types()).unwrap_or(&[]) {
|
||||||
.type_section()
|
|
||||||
.map(|ts| ts.types())
|
|
||||||
.unwrap_or(&[])
|
|
||||||
{
|
|
||||||
let type_id = alloc_func_type(ty.clone());
|
let type_id = alloc_func_type(ty.clone());
|
||||||
instance.push_type(type_id);
|
instance.push_type(type_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let imports = module.import_section().map(|is| is.entries()).unwrap_or(&[]);
|
let imports = module
|
||||||
|
.import_section()
|
||||||
|
.map(|is| is.entries())
|
||||||
|
.unwrap_or(&[]);
|
||||||
if imports.len() != extern_vals.len() {
|
if imports.len() != extern_vals.len() {
|
||||||
return Err(Error::Initialization(format!("extern_vals length is not equal to import section entries")));
|
return Err(Error::Initialization(format!(
|
||||||
|
"extern_vals length is not equal to import section entries"
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (import, extern_val) in Iterator::zip(imports.into_iter(), extern_vals.into_iter())
|
for (import, extern_val) in Iterator::zip(imports.into_iter(), extern_vals.into_iter())
|
||||||
{
|
{
|
||||||
match (import.external(), extern_val) {
|
match (import.external(), extern_val) {
|
||||||
(&External::Function(fn_type_idx), &ExternVal::Func(ref func)) => {
|
(&External::Function(fn_type_idx), &ExternVal::Func(ref func)) => {
|
||||||
let expected_fn_type = instance.type_by_index(fn_type_idx).expect("Due to validation function type should exists");
|
let expected_fn_type = instance
|
||||||
|
.type_by_index(fn_type_idx)
|
||||||
|
.expect("Due to validation function type should exists");
|
||||||
let actual_fn_type = func.func_type();
|
let actual_fn_type = func.func_type();
|
||||||
if expected_fn_type != actual_fn_type {
|
if expected_fn_type != actual_fn_type {
|
||||||
return Err(Error::Initialization(format!(
|
return Err(Error::Initialization(format!(
|
||||||
@ -341,7 +323,9 @@ impl ModuleInstance {
|
|||||||
for (index, (ty, body)) in
|
for (index, (ty, body)) in
|
||||||
Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate()
|
Iterator::zip(funcs.into_iter(), bodies.into_iter()).enumerate()
|
||||||
{
|
{
|
||||||
let func_type = instance.type_by_index(ty.type_ref()).expect("Due to validation type should exists");
|
let func_type = instance
|
||||||
|
.type_by_index(ty.type_ref())
|
||||||
|
.expect("Due to validation type should exists");
|
||||||
let labels = aux_data.labels.remove(&index).expect(
|
let labels = aux_data.labels.remove(&index).expect(
|
||||||
"At func validation time labels are collected; Collected labels are added by index; qed",
|
"At func validation time labels are collected; Collected labels are added by index; qed",
|
||||||
);
|
);
|
||||||
@ -463,8 +447,8 @@ impl ModuleInstance {
|
|||||||
// And run module's start function, if any
|
// And run module's start function, if any
|
||||||
if let Some(start_fn_idx) = module.start_section() {
|
if let Some(start_fn_idx) = module.start_section() {
|
||||||
let start_func = instance
|
let start_func = instance
|
||||||
.func_by_index(start_fn_idx)
|
.func_by_index(start_fn_idx)
|
||||||
.expect("Due to validation start function should exists");
|
.expect("Due to validation start function should exists");
|
||||||
FuncInstance::invoke(start_func, vec![], state)?;
|
FuncInstance::invoke(start_func, vec![], state)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,25 +464,29 @@ impl ModuleInstance {
|
|||||||
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
|
for import_entry in module.import_section().map(|s| s.entries()).unwrap_or(&[]) {
|
||||||
let module_name = import_entry.module();
|
let module_name = import_entry.module();
|
||||||
let field_name = import_entry.field();
|
let field_name = import_entry.field();
|
||||||
let resolver = imports.resolver(module_name).ok_or_else(|| Error::Initialization(format!("Module {} not found", module_name)))?;
|
let resolver = imports.resolver(module_name).ok_or_else(|| {
|
||||||
|
Error::Initialization(format!("Module {} not found", module_name))
|
||||||
|
})?;
|
||||||
let extern_val = match *import_entry.external() {
|
let extern_val = match *import_entry.external() {
|
||||||
External::Function(fn_ty_idx) => {
|
External::Function(fn_ty_idx) => {
|
||||||
// Module is not yet validated so we have to check type indexes.
|
// Module is not yet validated so we have to check type indexes.
|
||||||
let types = module.type_section().map(|s| s.types()).unwrap_or(&[]);
|
let types = module.type_section().map(|s| s.types()).unwrap_or(&[]);
|
||||||
let &Type::Function(ref func_type) = types.get(fn_ty_idx as usize)
|
let &Type::Function(ref func_type) =
|
||||||
.ok_or_else(|| Error::Validation(format!("Function type {} not found", fn_ty_idx)))?;
|
types.get(fn_ty_idx as usize).ok_or_else(|| {
|
||||||
|
Error::Validation(format!("Function type {} not found", fn_ty_idx))
|
||||||
|
})?;
|
||||||
|
|
||||||
let func = resolver.resolve_func(field_name, func_type)?;
|
let func = resolver.resolve_func(field_name, func_type)?;
|
||||||
ExternVal::Func(func)
|
ExternVal::Func(func)
|
||||||
},
|
}
|
||||||
External::Table(ref table_type) => {
|
External::Table(ref table_type) => {
|
||||||
let table = resolver.resolve_table(field_name, table_type)?;
|
let table = resolver.resolve_table(field_name, table_type)?;
|
||||||
ExternVal::Table(table)
|
ExternVal::Table(table)
|
||||||
},
|
}
|
||||||
External::Memory(ref memory_type) => {
|
External::Memory(ref memory_type) => {
|
||||||
let memory = resolver.resolve_memory(field_name, memory_type)?;
|
let memory = resolver.resolve_memory(field_name, memory_type)?;
|
||||||
ExternVal::Memory(memory)
|
ExternVal::Memory(memory)
|
||||||
},
|
}
|
||||||
External::Global(ref global_type) => {
|
External::Global(ref global_type) => {
|
||||||
let global = resolver.resolve_global(field_name, global_type)?;
|
let global = resolver.resolve_global(field_name, global_type)?;
|
||||||
ExternVal::Global(global)
|
ExternVal::Global(global)
|
||||||
@ -517,7 +505,10 @@ impl ModuleInstance {
|
|||||||
state: &mut St,
|
state: &mut St,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let func_instance = self.func_by_index(func_idx).ok_or_else(|| {
|
let func_instance = self.func_by_index(func_idx).ok_or_else(|| {
|
||||||
Error::Program(format!("Module doesn't contain function at index {}", func_idx))
|
Error::Program(format!(
|
||||||
|
"Module doesn't contain function at index {}",
|
||||||
|
func_idx
|
||||||
|
))
|
||||||
})?;
|
})?;
|
||||||
FuncInstance::invoke(func_instance, args, state)
|
FuncInstance::invoke(func_instance, args, state)
|
||||||
}
|
}
|
||||||
@ -528,14 +519,9 @@ impl ModuleInstance {
|
|||||||
args: Vec<RuntimeValue>,
|
args: Vec<RuntimeValue>,
|
||||||
state: &mut St,
|
state: &mut St,
|
||||||
) -> Result<Option<RuntimeValue>, Error> {
|
) -> Result<Option<RuntimeValue>, Error> {
|
||||||
let extern_val = self
|
let extern_val = self.export_by_name(func_name).ok_or_else(|| {
|
||||||
.export_by_name(func_name)
|
Error::Program(format!("Module doesn't have export {}", func_name))
|
||||||
.ok_or_else(|| {
|
})?;
|
||||||
Error::Program(format!(
|
|
||||||
"Module doesn't have export {}",
|
|
||||||
func_name
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let func_instance = match extern_val {
|
let func_instance = match extern_val {
|
||||||
ExternVal::Func(func_instance) => func_instance,
|
ExternVal::Func(func_instance) => func_instance,
|
||||||
@ -563,7 +549,9 @@ impl ImportResolver for ModuleInstance {
|
|||||||
Error::Validation(format!("Export {} not found", field_name))
|
Error::Validation(format!("Export {} not found", field_name))
|
||||||
})?
|
})?
|
||||||
.as_func()
|
.as_func()
|
||||||
.ok_or_else(|| Error::Validation(format!("Export {} is not a function", field_name)))?)
|
.ok_or_else(|| {
|
||||||
|
Error::Validation(format!("Export {} is not a function", field_name))
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_global(
|
fn resolve_global(
|
||||||
@ -576,7 +564,9 @@ impl ImportResolver for ModuleInstance {
|
|||||||
Error::Validation(format!("Export {} not found", field_name))
|
Error::Validation(format!("Export {} not found", field_name))
|
||||||
})?
|
})?
|
||||||
.as_global()
|
.as_global()
|
||||||
.ok_or_else(|| Error::Validation(format!("Export {} is not a global", field_name)))?)
|
.ok_or_else(|| {
|
||||||
|
Error::Validation(format!("Export {} is not a global", field_name))
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_memory(
|
fn resolve_memory(
|
||||||
@ -589,7 +579,9 @@ impl ImportResolver for ModuleInstance {
|
|||||||
Error::Validation(format!("Export {} not found", field_name))
|
Error::Validation(format!("Export {} not found", field_name))
|
||||||
})?
|
})?
|
||||||
.as_memory()
|
.as_memory()
|
||||||
.ok_or_else(|| Error::Validation(format!("Export {} is not a memory", field_name)))?)
|
.ok_or_else(|| {
|
||||||
|
Error::Validation(format!("Export {} is not a memory", field_name))
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_table(
|
fn resolve_table(
|
||||||
@ -602,7 +594,9 @@ impl ImportResolver for ModuleInstance {
|
|||||||
Error::Validation(format!("Export {} not found", field_name))
|
Error::Validation(format!("Export {} not found", field_name))
|
||||||
})?
|
})?
|
||||||
.as_table()
|
.as_table()
|
||||||
.ok_or_else(|| Error::Validation(format!("Export {} is not a table", field_name)))?)
|
.ok_or_else(|| {
|
||||||
|
Error::Validation(format!("Export {} is not a table", field_name))
|
||||||
|
})?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,7 +604,11 @@ fn alloc_func_type(func_type: FunctionType) -> Rc<FunctionType> {
|
|||||||
Rc::new(func_type)
|
Rc::new(func_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_func(module: &Rc<ModuleInstance>, func_type: Rc<FunctionType>, body: FuncBody) -> Rc<FuncInstance> {
|
fn alloc_func(
|
||||||
|
module: &Rc<ModuleInstance>,
|
||||||
|
func_type: Rc<FunctionType>,
|
||||||
|
body: FuncBody,
|
||||||
|
) -> Rc<FuncInstance> {
|
||||||
let func = FuncInstance::Internal {
|
let func = FuncInstance::Internal {
|
||||||
func_type,
|
func_type,
|
||||||
module: Rc::clone(module),
|
module: Rc::clone(module),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user