Skip to content

Commit

Permalink
Merge pull request #3556 from wasmerio/std-api
Browse files Browse the repository at this point in the history
Use standard API for js and sys for Module. Added Engine in js
  • Loading branch information
syrusakbary authored Mar 7, 2023
2 parents 4a1f779 + e61c206 commit 6d33d57
Show file tree
Hide file tree
Showing 96 changed files with 4,960 additions and 8,264 deletions.
3 changes: 2 additions & 1 deletion examples/imports_function_env_global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

let global_count = data.g_counter.get(&mut storemut).unwrap_i32();
data.g_counter
.set(&mut storemut, Value::I32(global_count + add));
.set(&mut storemut, Value::I32(global_count + add))
.unwrap();

*counter_ref += add;
*counter_ref
Expand Down
10 changes: 7 additions & 3 deletions examples/tunables_limit_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ use std::ptr::NonNull;
use wasmer::{
imports,
vm::{self, MemoryError, MemoryStyle, TableStyle, VMMemoryDefinition, VMTableDefinition},
wat2wasm, BaseTunables, Instance, Memory, MemoryType, Module, Pages, Store, TableType, Target,
Tunables,
wat2wasm, BaseTunables, Engine, Instance, Memory, MemoryType, Module, Pages, Store, TableType,
Target, Tunables,
};
use wasmer_compiler_cranelift::Cranelift;
// This is to be able to set the tunables
use wasmer::NativeEngineExt;

/// A custom tunables that allows you to set a memory limit.
///
Expand Down Expand Up @@ -140,9 +142,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Here is where the fun begins
let base = BaseTunables::for_target(&Target::default());
let tunables = LimitingTunables::new(base, Pages(24));
let mut engine: Engine = compiler.into();
engine.set_tunables(tunables);

// Create a store, that holds the engine and our custom tunables
let mut store = Store::new_with_tunables(compiler, tunables);
let mut store = Store::new(engine);

println!("Compiling module...");
let module = Module::new(&store, wasm_bytes)?;
Expand Down
1 change: 1 addition & 0 deletions lib/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ core = ["hashbrown"]
sys = [
"wasmer-compiler/translator",
"wasmer-compiler/compiler",
"std",
]
sys-default = ["sys", "wat", "cranelift"]
# - Compilers.
Expand Down
26 changes: 1 addition & 25 deletions lib/api/src/access.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::mem::MaybeUninit;

use crate::{WasmRef, WasmSlice};
use crate::mem_access::{WasmRef, WasmSlice};

pub(super) enum SliceCow<'a, T> {
#[allow(dead_code)]
Expand Down Expand Up @@ -167,30 +167,6 @@ where
}
}

impl<'a, T> WasmRefAccess<'a, T>
where
T: wasmer_types::ValueType,
{
/// Reads the address pointed to by this `WasmPtr` in a memory.
#[inline]
#[allow(clippy::clone_on_copy)]
pub fn read(&self) -> T
where
T: Clone,
{
self.as_ref().clone()
}

/// Writes to the address pointed to by this `WasmPtr` in a memory.
#[inline]
pub fn write(&mut self, val: T) {
// Note: Zero padding is not required here as its a typed copy which does
// not leak the bytes into the memory
// https://stackoverflow.com/questions/61114026/does-stdptrwrite-transfer-the-uninitialized-ness-of-the-bytes-it-writes
*(self.as_mut()) = val;
}
}

impl<'a, T> Drop for WasmRefAccess<'a, T>
where
T: wasmer_types::ValueType,
Expand Down
92 changes: 92 additions & 0 deletions lib/api/src/engine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use core::ops::Deref;

#[cfg(feature = "sys")]
use crate::sys::engine as engine_imp;
#[cfg(feature = "sys")]
pub(crate) use crate::sys::engine::default_engine;

#[cfg(feature = "js")]
use crate::js::engine as engine_imp;
#[cfg(feature = "js")]
pub(crate) use crate::js::engine::default_engine;

/// The engine type
#[derive(Clone, Debug)]
pub struct Engine(pub(crate) engine_imp::Engine);

impl Engine {
#[deprecated(
since = "3.2.0",
note = "engine.cloned() has been deprecated in favor of engine.clone()"
)]
/// Returns the [`Engine`].
pub fn cloned(&self) -> Self {
self.clone()
}

/// Returns the deterministic id of this engine
pub fn deterministic_id(&self) -> &str {
self.0.deterministic_id()
}
}

impl AsEngineRef for Engine {
fn as_engine_ref(&self) -> EngineRef {
EngineRef { inner: self }
}
}

impl Default for Engine {
fn default() -> Self {
Self(default_engine())
}
}

impl<T: Into<engine_imp::Engine>> From<T> for Engine {
fn from(t: T) -> Self {
Self(t.into())
}
}

/// A temporary handle to an [`Engine`]
/// EngineRef can be used to build a [`Module`][wasmer::Module]
/// It can be created directly with an [`Engine`]
/// Or from anything implementing [`AsEngineRef`]
/// like from [`Store`][wasmer::Store] typicaly.
pub struct EngineRef<'a> {
/// The inner engine
pub(crate) inner: &'a Engine,
}

impl<'a> EngineRef<'a> {
/// Get inner [`Engine`]
pub fn engine(&self) -> &Engine {
self.inner
}
/// Create an EngineRef from an Engine
pub fn new(engine: &'a Engine) -> Self {
EngineRef { inner: engine }
}
}

/// Helper trait for a value that is convertible to a [`EngineRef`].
pub trait AsEngineRef {
/// Returns a `EngineRef` pointing to the underlying context.
fn as_engine_ref(&self) -> EngineRef<'_>;
}

impl AsEngineRef for EngineRef<'_> {
fn as_engine_ref(&self) -> EngineRef<'_> {
EngineRef { inner: self.inner }
}
}

impl<P> AsEngineRef for P
where
P: Deref,
P::Target: AsEngineRef,
{
fn as_engine_ref(&self) -> EngineRef<'_> {
(**self).as_engine_ref()
}
}
47 changes: 47 additions & 0 deletions lib/api/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#[cfg(feature = "js")]
pub use crate::js::errors::{LinkError, RuntimeError};
use thiserror::Error;
#[cfg(feature = "sys")]
pub use wasmer_compiler::{LinkError, RuntimeError};

/// An error while instantiating a module.
///
/// This is not a common WebAssembly error, however
/// we need to differentiate from a `LinkError` (an error
/// that happens while linking, on instantiation), a
/// Trap that occurs when calling the WebAssembly module
/// start function, and an error when initializing the user's
/// host environments.
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum InstantiationError {
/// A linking ocurred during instantiation.
#[cfg_attr(feature = "std", error(transparent))]
Link(LinkError),

/// A runtime error occured while invoking the start function
#[cfg_attr(feature = "std", error(transparent))]
Start(RuntimeError),

/// The module was compiled with a CPU feature that is not available on
/// the current host.
#[cfg_attr(feature = "std", error("missing required CPU features: {0:?}"))]
CpuFeature(String),

/// Import from a different [`Store`].
/// This error occurs when an import from a different store is used.
#[cfg_attr(feature = "std", error("cannot mix imports from different stores"))]
DifferentStores,

/// Import from a different Store.
/// This error occurs when an import from a different store is used.
#[cfg_attr(feature = "std", error("incorrect OS or architecture"))]
DifferentArchOS,
}

#[cfg(feature = "core")]
impl std::fmt::Display for InstantiationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "InstantiationError")
}
}
12 changes: 3 additions & 9 deletions lib/api/src/sys/exports.rs → lib/api/src/exports.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use super::store::AsStoreRef;
use crate::sys::externals::{Extern, Function, Global, Memory, Table};
use crate::sys::native::TypedFunction;
use crate::sys::WasmTypeList;
use crate::store::AsStoreRef;
use crate::{Extern, Function, Global, Memory, Table, TypedFunction, WasmTypeList};
use indexmap::IndexMap;
use std::fmt;
use std::iter::{ExactSizeIterator, FromIterator};
Expand All @@ -18,9 +16,7 @@ use thiserror::Error;
///
/// ```should_panic
/// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError};
/// # use wasmer::FunctionEnv;
/// # let mut store = Store::default();
/// # let env = FunctionEnv::new(&mut store, ());
/// # let wasm_bytes = wat2wasm(r#"
/// # (module
/// # (global $one (export "glob") f32 (f32.const 1)))
Expand All @@ -37,9 +33,7 @@ use thiserror::Error;
///
/// ```should_panic
/// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value, ExportError};
/// # use wasmer::FunctionEnv;
/// # let mut store = Store::default();
/// # let env = FunctionEnv::new(&mut store, ());
/// # let wasm_bytes = wat2wasm("(module)".as_bytes()).unwrap();
/// # let module = Module::new(&store, wasm_bytes).unwrap();
/// # let import_object = imports! {};
Expand All @@ -63,7 +57,7 @@ pub enum ExportError {
/// the types of instances.
///
/// TODO: add examples of using exports
#[derive(Clone, Default)]
#[derive(Clone, Default, PartialEq, Eq)]
pub struct Exports {
map: IndexMap<String, Extern>,
}
Expand Down
57 changes: 57 additions & 0 deletions lib/api/src/extern_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use std::any::Any;

use crate::store::{AsStoreMut, AsStoreRef};

#[cfg(feature = "js")]
use crate::js::extern_ref as extern_ref_imp;
#[cfg(feature = "sys")]
use crate::sys::extern_ref as extern_ref_imp;
use crate::vm::VMExternRef;

#[derive(Debug, Clone)]
#[repr(transparent)]
/// An opaque reference to some data. This reference can be passed through Wasm.
pub struct ExternRef(pub(crate) extern_ref_imp::ExternRef);

impl ExternRef {
/// Make a new extern reference
pub fn new<T>(store: &mut impl AsStoreMut, value: T) -> Self
where
T: Any + Send + Sync + 'static + Sized,
{
Self(extern_ref_imp::ExternRef::new(store, value))
}

/// Try to downcast to the given value.
pub fn downcast<'a, T>(&self, store: &'a impl AsStoreRef) -> Option<&'a T>
where
T: Any + Send + Sync + 'static + Sized,
{
self.0.downcast(store)
}

pub(crate) fn vm_externref(&self) -> VMExternRef {
self.0.vm_externref()
}

pub(crate) unsafe fn from_vm_externref(
store: &mut impl AsStoreMut,
vm_externref: VMExternRef,
) -> Self {
Self(extern_ref_imp::ExternRef::from_vm_externref(
store,
vm_externref,
))
}

/// Checks whether this `ExternRef` can be used with the given context.
///
/// Primitive (`i32`, `i64`, etc) and null funcref/externref values are not
/// tied to a context and can be freely shared between contexts.
///
/// Externref and funcref values are tied to a context and can only be used
/// with that context.
pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
self.0.is_from_store(store)
}
}
Loading

0 comments on commit 6d33d57

Please sign in to comment.