Create a Context class to group together various state objects.
This commit is contained in:
@@ -23,6 +23,7 @@ failure = { version = "0.1.3", default-features = false }
|
|||||||
failure_derive = { version = "0.1.3", default-features = false }
|
failure_derive = { version = "0.1.3", default-features = false }
|
||||||
target-lexicon = { version = "0.2.0", default-features = false }
|
target-lexicon = { version = "0.2.0", default-features = false }
|
||||||
hashbrown = { version = "0.1.8", optional = true }
|
hashbrown = { version = "0.1.8", optional = true }
|
||||||
|
wasmparser = "0.23.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
|||||||
182
lib/jit/src/context.rs
Normal file
182
lib/jit/src/context.rs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
use crate::{
|
||||||
|
instantiate, ActionError, ActionOutcome, Compiler, Instance, InstanceIndex, Namespace,
|
||||||
|
RuntimeValue, SetupError,
|
||||||
|
};
|
||||||
|
use cranelift_codegen::isa::TargetIsa;
|
||||||
|
use std::borrow::ToOwned;
|
||||||
|
use std::boxed::Box;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::string::{String, ToString};
|
||||||
|
use std::{fmt, str};
|
||||||
|
use wasmparser::{validate, OperatorValidatorConfig, ValidatingParserConfig};
|
||||||
|
|
||||||
|
/// Indicates an unknown instance was specified.
|
||||||
|
#[derive(Fail, Debug)]
|
||||||
|
pub struct UnknownInstance {
|
||||||
|
instance_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for UnknownInstance {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "no instance {} present", self.instance_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error message used by `WastContext`.
|
||||||
|
#[derive(Fail, Debug)]
|
||||||
|
pub enum ContextError {
|
||||||
|
/// An unknown instance name was used.
|
||||||
|
Instance(UnknownInstance),
|
||||||
|
/// An error occured while performing an action.
|
||||||
|
Action(ActionError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ContextError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
ContextError::Instance(ref error) => error.fmt(f),
|
||||||
|
ContextError::Action(ref error) => error.fmt(f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A convenient context for compiling and executing WebAssembly instances.
|
||||||
|
pub struct Context {
|
||||||
|
namespace: Namespace,
|
||||||
|
compiler: Box<Compiler>,
|
||||||
|
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
/// Construct a new instance of `Context`.
|
||||||
|
pub fn new(compiler: Box<Compiler>) -> Self {
|
||||||
|
Self {
|
||||||
|
namespace: Namespace::new(),
|
||||||
|
compiler,
|
||||||
|
global_exports: Rc::new(RefCell::new(HashMap::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a new instance of `Context` with the given target.
|
||||||
|
pub fn with_isa(isa: Box<TargetIsa>) -> Self {
|
||||||
|
Self::new(Box::new(Compiler::new(isa)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate(&mut self, data: &[u8]) -> Result<(), String> {
|
||||||
|
let config = ValidatingParserConfig {
|
||||||
|
operator_config: OperatorValidatorConfig {
|
||||||
|
enable_threads: false,
|
||||||
|
enable_reference_types: false,
|
||||||
|
},
|
||||||
|
mutable_global_imports: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Fix Cranelift to be able to perform validation itself, rather
|
||||||
|
// than calling into wasmparser ourselves here.
|
||||||
|
if validate(data, Some(config)) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
// TODO: Work with wasmparser to get better error messages.
|
||||||
|
Err("module did not validate".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instantiate(&mut self, data: &[u8]) -> Result<Instance, SetupError> {
|
||||||
|
self.validate(&data).map_err(SetupError::Validate)?;
|
||||||
|
|
||||||
|
instantiate(
|
||||||
|
&mut *self.compiler,
|
||||||
|
&data,
|
||||||
|
&mut self.namespace,
|
||||||
|
Rc::clone(&mut self.global_exports),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the instance index for the instance with the given name.
|
||||||
|
pub fn get_instance_index(
|
||||||
|
&mut self,
|
||||||
|
instance_name: &str,
|
||||||
|
) -> Result<InstanceIndex, UnknownInstance> {
|
||||||
|
self.namespace
|
||||||
|
.get_instance_index(instance_name)
|
||||||
|
.ok_or_else(|| UnknownInstance {
|
||||||
|
instance_name: instance_name.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Instantiate a module instance and register the instance.
|
||||||
|
pub fn instantiate_module(
|
||||||
|
&mut self,
|
||||||
|
instance_name: Option<String>,
|
||||||
|
data: &[u8],
|
||||||
|
) -> Result<InstanceIndex, ActionError> {
|
||||||
|
let instance = self.instantiate(data).map_err(ActionError::Setup)?;
|
||||||
|
Ok(self.instance(instance_name, instance))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Install a new `Instance` in this `Namespace`, optionally with the
|
||||||
|
/// given name, and return its index.
|
||||||
|
pub fn instance(&mut self, instance_name: Option<String>, instance: Instance) -> InstanceIndex {
|
||||||
|
self.namespace.instance(instance_name, instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register an additional name for an existing registered instance.
|
||||||
|
pub fn alias(&mut self, name: &str, as_name: String) -> Result<(), UnknownInstance> {
|
||||||
|
let index = self.get_instance_index(&name)?;
|
||||||
|
self.alias_for_indexed(index, as_name);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register an additional name for an existing registered instance.
|
||||||
|
pub fn alias_for_indexed(&mut self, index: InstanceIndex, as_name: String) {
|
||||||
|
self.namespace.alias_for_indexed(index, as_name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invoke an exported function from an instance.
|
||||||
|
pub fn invoke(
|
||||||
|
&mut self,
|
||||||
|
instance_name: &str,
|
||||||
|
field: &str,
|
||||||
|
args: &[RuntimeValue],
|
||||||
|
) -> Result<ActionOutcome, ContextError> {
|
||||||
|
let index = self
|
||||||
|
.get_instance_index(&instance_name)
|
||||||
|
.map_err(ContextError::Instance)?;
|
||||||
|
self.invoke_indexed(index, field, args)
|
||||||
|
.map_err(ContextError::Action)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Invoke an exported function from an instance.
|
||||||
|
pub fn invoke_indexed(
|
||||||
|
&mut self,
|
||||||
|
index: InstanceIndex,
|
||||||
|
field: &str,
|
||||||
|
args: &[RuntimeValue],
|
||||||
|
) -> Result<ActionOutcome, ActionError> {
|
||||||
|
self.namespace
|
||||||
|
.invoke(&mut *self.compiler, index, field, &args)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the value of an exported global variable from an instance.
|
||||||
|
pub fn get(&mut self, instance_name: &str, field: &str) -> Result<ActionOutcome, ContextError> {
|
||||||
|
let index = self
|
||||||
|
.get_instance_index(&instance_name)
|
||||||
|
.map_err(ContextError::Instance)?;
|
||||||
|
self.get_indexed(index, field).map_err(ContextError::Action)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the value of an exported global variable from an instance.
|
||||||
|
pub fn get_indexed(
|
||||||
|
&mut self,
|
||||||
|
index: InstanceIndex,
|
||||||
|
field: &str,
|
||||||
|
) -> Result<ActionOutcome, ActionError> {
|
||||||
|
self.namespace
|
||||||
|
.get(index, field)
|
||||||
|
.map(|value| ActionOutcome::Returned {
|
||||||
|
values: vec![value],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,6 +44,7 @@ extern crate failure_derive;
|
|||||||
mod action;
|
mod action;
|
||||||
mod code_memory;
|
mod code_memory;
|
||||||
mod compiler;
|
mod compiler;
|
||||||
|
mod context;
|
||||||
mod instantiate;
|
mod instantiate;
|
||||||
mod link;
|
mod link;
|
||||||
mod namespace;
|
mod namespace;
|
||||||
@@ -52,6 +53,7 @@ mod target_tunables;
|
|||||||
|
|
||||||
pub use crate::action::{ActionError, ActionOutcome, RuntimeValue};
|
pub use crate::action::{ActionError, ActionOutcome, RuntimeValue};
|
||||||
pub use crate::compiler::Compiler;
|
pub use crate::compiler::Compiler;
|
||||||
|
pub use crate::context::{Context, ContextError, UnknownInstance};
|
||||||
pub use crate::instantiate::{instantiate, CompiledModule, SetupError};
|
pub use crate::instantiate::{instantiate, CompiledModule, SetupError};
|
||||||
pub use crate::link::link_module;
|
pub use crate::link::link_module;
|
||||||
pub use crate::namespace::{InstanceIndex, Namespace};
|
pub use crate::namespace::{InstanceIndex, Namespace};
|
||||||
|
|||||||
@@ -39,22 +39,22 @@ impl Namespace {
|
|||||||
|
|
||||||
/// Install a new `Instance` in this `Namespace`, optionally with the
|
/// Install a new `Instance` in this `Namespace`, optionally with the
|
||||||
/// given name, and return its index.
|
/// given name, and return its index.
|
||||||
pub fn instance(&mut self, instance_name: Option<&str>, instance: Instance) -> InstanceIndex {
|
pub fn instance(&mut self, instance_name: Option<String>, instance: Instance) -> InstanceIndex {
|
||||||
let index = self.instances.push(instance);
|
let index = self.instances.push(instance);
|
||||||
if let Some(instance_name) = instance_name {
|
if let Some(instance_name) = instance_name {
|
||||||
self.names.insert(instance_name.into(), index);
|
self.names.insert(instance_name, index);
|
||||||
}
|
}
|
||||||
index
|
index
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the instance index registered with the given `instance_name`.
|
/// Get the instance index registered with the given `instance_name`.
|
||||||
pub fn get_instance_index(&mut self, instance_name: &str) -> Option<&mut InstanceIndex> {
|
pub fn get_instance_index(&mut self, instance_name: &str) -> Option<InstanceIndex> {
|
||||||
self.names.get_mut(instance_name)
|
self.names.get_mut(instance_name).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register an instance with a given name.
|
/// Register an additional name for an existing registered instance.
|
||||||
pub fn register(&mut self, name: String, index: InstanceIndex) {
|
pub fn alias_for_indexed(&mut self, existing_index: InstanceIndex, new_name: String) {
|
||||||
self.names.insert(name, index);
|
self.names.insert(new_name, existing_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoke an exported function from an instance.
|
/// Invoke an exported function from an instance.
|
||||||
|
|||||||
@@ -760,8 +760,6 @@ impl Instance {
|
|||||||
pub fn lookup(&mut self, field: &str) -> Option<Export> {
|
pub fn lookup(&mut self, field: &str) -> Option<Export> {
|
||||||
let export = if let Some(export) = self.module.exports.get(field) {
|
let export = if let Some(export) = self.module.exports.get(field) {
|
||||||
export.clone()
|
export.clone()
|
||||||
} else if let Some(export) = self.mmap_field.contents().lookup_global_export(field) {
|
|
||||||
return Some(export.clone());
|
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ wabt = "0.7"
|
|||||||
target-lexicon = "0.2.0"
|
target-lexicon = "0.2.0"
|
||||||
failure = { version = "0.1.3", default-features = false }
|
failure = { version = "0.1.3", default-features = false }
|
||||||
failure_derive = { version = "0.1.3", default-features = false }
|
failure_derive = { version = "0.1.3", default-features = false }
|
||||||
wasmparser = "0.23.0"
|
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
maintenance = { status = "experimental" }
|
maintenance = { status = "experimental" }
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
use crate::spectest::instantiate_spectest;
|
use crate::spectest::instantiate_spectest;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
|
||||||
use std::{fmt, fs, io, str};
|
use std::{fmt, fs, io, str};
|
||||||
use wabt::script::{Action, Command, CommandKind, ModuleBinary, ScriptParser, Value};
|
use wabt::script::{Action, Command, CommandKind, ModuleBinary, ScriptParser, Value};
|
||||||
use wasmparser::{validate, OperatorValidatorConfig, ValidatingParserConfig};
|
|
||||||
use wasmtime_jit::{
|
use wasmtime_jit::{
|
||||||
instantiate, ActionError, ActionOutcome, Compiler, Instance, InstanceIndex, InstantiationError,
|
ActionError, ActionOutcome, Compiler, Context, InstanceIndex, InstantiationError, RuntimeValue,
|
||||||
Namespace, RuntimeValue, SetupError,
|
UnknownInstance,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Translate from a `script::Value` to a `RuntimeValue`.
|
/// Translate from a `script::Value` to a `RuntimeValue`.
|
||||||
@@ -22,21 +18,6 @@ fn runtime_value(v: Value) -> RuntimeValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates an unknown instance was specified.
|
|
||||||
#[derive(Fail, Debug)]
|
|
||||||
pub struct UnknownInstance {
|
|
||||||
instance: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for UnknownInstance {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self.instance {
|
|
||||||
None => write!(f, "no default instance present"),
|
|
||||||
Some(ref name) => write!(f, "no instance {} present", name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Error message used by `WastContext`.
|
/// Error message used by `WastContext`.
|
||||||
#[derive(Fail, Debug)]
|
#[derive(Fail, Debug)]
|
||||||
pub enum WastError {
|
pub enum WastError {
|
||||||
@@ -44,6 +25,8 @@ pub enum WastError {
|
|||||||
Assert(String),
|
Assert(String),
|
||||||
/// An unknown instance name was used.
|
/// An unknown instance name was used.
|
||||||
Instance(UnknownInstance),
|
Instance(UnknownInstance),
|
||||||
|
/// No default instance has been registered yet.
|
||||||
|
NoDefaultInstance,
|
||||||
/// An error occured while performing an action.
|
/// An error occured while performing an action.
|
||||||
Action(ActionError),
|
Action(ActionError),
|
||||||
/// An action trapped.
|
/// An action trapped.
|
||||||
@@ -63,6 +46,7 @@ impl fmt::Display for WastError {
|
|||||||
match *self {
|
match *self {
|
||||||
WastError::Assert(ref message) => write!(f, "Assert command failed: {}", message),
|
WastError::Assert(ref message) => write!(f, "Assert command failed: {}", message),
|
||||||
WastError::Instance(ref error) => error.fmt(f),
|
WastError::Instance(ref error) => error.fmt(f),
|
||||||
|
WastError::NoDefaultInstance => write!(f, "no default instance defined yet"),
|
||||||
WastError::Action(ref error) => error.fmt(f),
|
WastError::Action(ref error) => error.fmt(f),
|
||||||
WastError::Trap(ref message) => write!(f, "trap: {}", message),
|
WastError::Trap(ref message) => write!(f, "trap: {}", message),
|
||||||
WastError::Type(ref message) => write!(f, "type error: {}", message),
|
WastError::Type(ref message) => write!(f, "type error: {}", message),
|
||||||
@@ -85,10 +69,11 @@ pub struct WastFileError {
|
|||||||
/// The wast test script language allows modules to be defined and actions
|
/// The wast test script language allows modules to be defined and actions
|
||||||
/// to be performed on them.
|
/// to be performed on them.
|
||||||
pub struct WastContext {
|
pub struct WastContext {
|
||||||
/// A namespace of wasm modules, keyed by an optional name.
|
/// Wast files have a concept of a "current" module, which is the most
|
||||||
|
/// recently defined.
|
||||||
current: Option<InstanceIndex>,
|
current: Option<InstanceIndex>,
|
||||||
namespace: Namespace,
|
|
||||||
compiler: Box<Compiler>,
|
context: Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WastContext {
|
impl WastContext {
|
||||||
@@ -96,56 +81,23 @@ impl WastContext {
|
|||||||
pub fn new(compiler: Box<Compiler>) -> Self {
|
pub fn new(compiler: Box<Compiler>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
current: None,
|
current: None,
|
||||||
namespace: Namespace::new(),
|
context: Context::new(compiler),
|
||||||
compiler,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate(&mut self, data: &[u8]) -> Result<(), String> {
|
fn get_instance_index(
|
||||||
let config = ValidatingParserConfig {
|
&mut self,
|
||||||
operator_config: OperatorValidatorConfig {
|
instance_name: Option<&str>,
|
||||||
enable_threads: false,
|
) -> Result<InstanceIndex, WastError> {
|
||||||
enable_reference_types: false,
|
let index = if let Some(instance_name) = instance_name {
|
||||||
},
|
self.context
|
||||||
mutable_global_imports: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: Fix Cranelift to be able to perform validation itself, rather
|
|
||||||
// than calling into wasmparser ourselves here.
|
|
||||||
if validate(data, Some(config)) {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
// TODO: Work with wasmparser to get better error messages.
|
|
||||||
Err("module did not validate".to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn instantiate(&mut self, module: ModuleBinary) -> Result<Instance, SetupError> {
|
|
||||||
let data = module.into_vec();
|
|
||||||
|
|
||||||
self.validate(&data).map_err(SetupError::Validate)?;
|
|
||||||
|
|
||||||
instantiate(
|
|
||||||
&mut *self.compiler,
|
|
||||||
&data,
|
|
||||||
&mut self.namespace,
|
|
||||||
Rc::new(RefCell::new(HashMap::new())),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_index(&mut self, instance_name: &Option<String>) -> Result<InstanceIndex, WastError> {
|
|
||||||
let index = *if let Some(instance_name) = instance_name {
|
|
||||||
self.namespace
|
|
||||||
.get_instance_index(instance_name)
|
.get_instance_index(instance_name)
|
||||||
.ok_or_else(|| {
|
.map_err(WastError::Instance)
|
||||||
WastError::Instance(UnknownInstance {
|
|
||||||
instance: Some(instance_name.to_string()),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
self.current
|
self.current
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.ok_or_else(|| WastError::Instance(UnknownInstance { instance: None }))
|
.cloned()
|
||||||
|
.ok_or_else(|| WastError::NoDefaultInstance)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
Ok(index)
|
Ok(index)
|
||||||
@@ -154,7 +106,7 @@ impl WastContext {
|
|||||||
/// Register "spectest" which is used by the spec testsuite.
|
/// Register "spectest" which is used by the spec testsuite.
|
||||||
pub fn register_spectest(&mut self) -> Result<(), InstantiationError> {
|
pub fn register_spectest(&mut self) -> Result<(), InstantiationError> {
|
||||||
let instance = instantiate_spectest()?;
|
let instance = instantiate_spectest()?;
|
||||||
self.namespace.instance(Some("spectest"), instance);
|
self.context.instance(Some("spectest".to_owned()), instance);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,18 +131,17 @@ impl WastContext {
|
|||||||
instance_name: Option<String>,
|
instance_name: Option<String>,
|
||||||
module: ModuleBinary,
|
module: ModuleBinary,
|
||||||
) -> Result<(), ActionError> {
|
) -> Result<(), ActionError> {
|
||||||
let instance = self.instantiate(module).map_err(ActionError::Setup)?;
|
|
||||||
let index = self
|
let index = self
|
||||||
.namespace
|
.context
|
||||||
.instance(instance_name.as_ref().map(String::as_str), instance);
|
.instantiate_module(instance_name, &module.into_vec())?;
|
||||||
self.current = Some(index);
|
self.current = Some(index);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register an instance to make it available for performing actions.
|
/// Register an instance to make it available for performing actions.
|
||||||
fn register(&mut self, name: Option<String>, as_name: String) -> Result<(), WastError> {
|
fn register(&mut self, name: Option<String>, as_name: String) -> Result<(), WastError> {
|
||||||
let index = self.get_index(&name)?;
|
let index = self.get_instance_index(name.as_ref().map(|x| &**x))?;
|
||||||
self.namespace.register(as_name, index);
|
self.context.alias_for_indexed(index, as_name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +156,9 @@ impl WastContext {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|arg| runtime_value(*arg))
|
.map(|arg| runtime_value(*arg))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let index = self.get_index(&instance_name)?;
|
let index = self.get_instance_index(instance_name.as_ref().map(|x| &**x))?;
|
||||||
self.namespace
|
self.context
|
||||||
.invoke(&mut *self.compiler, index, field, &value_args)
|
.invoke_indexed(index, field, &value_args)
|
||||||
.map_err(WastError::Action)
|
.map_err(WastError::Action)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,14 +168,10 @@ impl WastContext {
|
|||||||
instance_name: Option<String>,
|
instance_name: Option<String>,
|
||||||
field: &str,
|
field: &str,
|
||||||
) -> Result<ActionOutcome, WastError> {
|
) -> Result<ActionOutcome, WastError> {
|
||||||
let index = self.get_index(&instance_name)?;
|
let index = self.get_instance_index(instance_name.as_ref().map(|x| &**x))?;
|
||||||
let value = self
|
self.context
|
||||||
.namespace
|
.get_indexed(index, field)
|
||||||
.get(index, field)
|
.map_err(WastError::Action)
|
||||||
.map_err(WastError::Action)?;
|
|
||||||
Ok(ActionOutcome::Returned {
|
|
||||||
values: vec![value],
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform the action of a `PerformAction`.
|
/// Perform the action of a `PerformAction`.
|
||||||
|
|||||||
@@ -39,18 +39,14 @@ use cranelift_native;
|
|||||||
use docopt::Docopt;
|
use docopt::Docopt;
|
||||||
use file_per_thread_logger;
|
use file_per_thread_logger;
|
||||||
use pretty_env_logger;
|
use pretty_env_logger;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::exit;
|
use std::process::exit;
|
||||||
use std::rc::Rc;
|
|
||||||
use wabt;
|
use wabt;
|
||||||
use wasmtime_jit::{instantiate, ActionOutcome, Compiler, Namespace};
|
use wasmtime_jit::{ActionOutcome, Context};
|
||||||
use wasmtime_wast::instantiate_spectest;
|
use wasmtime_wast::instantiate_spectest;
|
||||||
|
|
||||||
static LOG_FILENAME_PREFIX: &str = "wasmtime.dbg.";
|
static LOG_FILENAME_PREFIX: &str = "wasmtime.dbg.";
|
||||||
@@ -121,26 +117,17 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
||||||
let mut compiler = Compiler::new(isa);
|
let mut context = Context::with_isa(isa);
|
||||||
|
|
||||||
let mut namespace = Namespace::new();
|
|
||||||
let global_exports = Rc::new(RefCell::new(HashMap::new()));
|
|
||||||
|
|
||||||
// Make spectest available by default.
|
// Make spectest available by default.
|
||||||
namespace.instance(
|
context.instance(
|
||||||
Some("spectest"),
|
Some("spectest".to_owned()),
|
||||||
instantiate_spectest().expect("instantiating spectest"),
|
instantiate_spectest().expect("instantiating spectest"),
|
||||||
);
|
);
|
||||||
|
|
||||||
for filename in &args.arg_file {
|
for filename in &args.arg_file {
|
||||||
let path = Path::new(&filename);
|
let path = Path::new(&filename);
|
||||||
match handle_module(
|
match handle_module(&mut context, &args, path) {
|
||||||
&mut compiler,
|
|
||||||
&mut namespace,
|
|
||||||
Rc::clone(&global_exports),
|
|
||||||
&args,
|
|
||||||
path,
|
|
||||||
) {
|
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(message) => {
|
Err(message) => {
|
||||||
let name = path.as_os_str().to_string_lossy();
|
let name = path.as_os_str().to_string_lossy();
|
||||||
@@ -151,13 +138,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_module(
|
fn handle_module(context: &mut Context, args: &Args, path: &Path) -> Result<(), String> {
|
||||||
compiler: &mut Compiler,
|
|
||||||
namespace: &mut Namespace,
|
|
||||||
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
|
|
||||||
args: &Args,
|
|
||||||
path: &Path,
|
|
||||||
) -> Result<(), String> {
|
|
||||||
let mut data =
|
let mut data =
|
||||||
read_to_end(path.to_path_buf()).map_err(|err| String::from(err.description()))?;
|
read_to_end(path.to_path_buf()).map_err(|err| String::from(err.description()))?;
|
||||||
|
|
||||||
@@ -167,16 +148,14 @@ fn handle_module(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new `Instance` by compiling and instantiating a wasm module.
|
// Create a new `Instance` by compiling and instantiating a wasm module.
|
||||||
let instance =
|
let index = context
|
||||||
instantiate(compiler, &data, namespace, global_exports).map_err(|e| e.to_string())?;
|
.instantiate_module(None, &data)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
// Register it in the namespace.
|
|
||||||
let index = namespace.instance(None, instance);
|
|
||||||
|
|
||||||
// If a function to invoke was given, invoke it.
|
// If a function to invoke was given, invoke it.
|
||||||
if let Some(ref f) = args.flag_invoke {
|
if let Some(ref f) = args.flag_invoke {
|
||||||
match namespace
|
match context
|
||||||
.invoke(compiler, index, f, &[])
|
.invoke_indexed(index, f, &[])
|
||||||
.map_err(|e| e.to_string())?
|
.map_err(|e| e.to_string())?
|
||||||
{
|
{
|
||||||
ActionOutcome::Returned { .. } => {}
|
ActionOutcome::Returned { .. } => {}
|
||||||
|
|||||||
Reference in New Issue
Block a user