use crate::sys::tunables::BaseTunables;
use std::fmt;
use std::sync::{Arc, RwLock};
#[cfg(feature = "compiler")]
use wasmer_compiler::{Engine, EngineBuilder, Tunables};
use wasmer_vm::{init_traps, TrapHandler, TrapHandlerFn};
use wasmer_vm::StoreObjects;
pub(crate) struct StoreInner {
pub(crate) objects: StoreObjects,
pub(crate) engine: Engine,
pub(crate) tunables: Box<dyn Tunables + Send + Sync>,
pub(crate) trap_handler: Option<Box<TrapHandlerFn<'static>>>,
}
pub struct Store {
pub(crate) inner: Box<StoreInner>,
engine: Engine,
trap_handler: Arc<RwLock<Option<Box<TrapHandlerFn<'static>>>>>,
}
impl Store {
#[cfg(feature = "compiler")]
pub fn new(engine: impl Into<Engine>) -> Self {
let engine = engine.into();
let target = engine.target().clone();
Self::new_with_tunables(engine, BaseTunables::for_target(&target))
}
#[deprecated(
since = "3.0.0",
note = "Store::new_with_engine has been deprecated in favor of Store::new"
)]
pub fn new_with_engine(engine: impl Into<Engine>) -> Self {
Self::new(engine)
}
pub fn set_trap_handler(&mut self, handler: Option<Box<TrapHandlerFn<'static>>>) {
self.inner.trap_handler = handler;
}
pub fn new_with_tunables(
engine: impl Into<Engine>,
tunables: impl Tunables + Send + Sync + 'static,
) -> Self {
let engine = engine.into();
init_traps();
Self {
inner: Box::new(StoreInner {
objects: Default::default(),
engine: engine.cloned(),
tunables: Box::new(tunables),
trap_handler: None,
}),
engine: engine.cloned(),
trap_handler: Arc::new(RwLock::new(None)),
}
}
pub fn tunables(&self) -> &dyn Tunables {
self.inner.tunables.as_ref()
}
pub fn engine(&self) -> &Engine {
&self.engine
}
pub fn same(a: &Self, b: &Self) -> bool {
a.engine.id() == b.engine.id()
}
}
impl PartialEq for Store {
fn eq(&self, other: &Self) -> bool {
Self::same(self, other)
}
}
unsafe impl TrapHandler for Store {
fn custom_trap_handler(&self, call: &dyn Fn(&TrapHandlerFn) -> bool) -> bool {
if let Some(handler) = self.trap_handler.read().unwrap().as_ref() {
call(handler)
} else {
false
}
}
}
unsafe impl Send for Store {}
unsafe impl Sync for Store {}
#[cfg(feature = "compiler")]
impl Default for Store {
fn default() -> Self {
#[allow(unreachable_code)]
#[cfg(any(feature = "cranelift", feature = "llvm", feature = "singlepass"))]
fn get_config() -> impl wasmer_compiler::CompilerConfig + 'static {
cfg_if::cfg_if! {
if #[cfg(feature = "cranelift")] {
wasmer_compiler_cranelift::Cranelift::default()
} else if #[cfg(feature = "llvm")] {
wasmer_compiler_llvm::LLVM::default()
} else if #[cfg(feature = "singlepass")] {
wasmer_compiler_singlepass::Singlepass::default()
} else {
compile_error!("No default compiler chosen")
}
}
}
#[allow(unreachable_code, unused_mut)]
fn get_engine() -> Engine {
cfg_if::cfg_if! {
if #[cfg(feature = "compiler")] {
cfg_if::cfg_if! {
if #[cfg(any(feature = "cranelift", feature = "llvm", feature = "singlepass"))]
{
let config = get_config();
EngineBuilder::new(Box::new(config) as Box<dyn wasmer_compiler::CompilerConfig>)
.engine()
} else {
EngineBuilder::headless()
.engine()
}
}
} else {
compile_error!("No default engine chosen")
}
}
}
let engine = get_engine();
let tunables = BaseTunables::for_target(engine.target());
Self::new_with_tunables(&engine, tunables)
}
}
impl AsStoreRef for Store {
fn as_store_ref(&self) -> StoreRef<'_> {
StoreRef { inner: &self.inner }
}
}
impl AsStoreMut for Store {
fn as_store_mut(&mut self) -> StoreMut<'_> {
StoreMut {
inner: &mut self.inner,
}
}
fn objects_mut(&mut self) -> &mut StoreObjects {
&mut self.inner.objects
}
}
impl fmt::Debug for Store {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Store").finish()
}
}
pub struct StoreRef<'a> {
pub(crate) inner: &'a StoreInner,
}
impl<'a> StoreRef<'a> {
pub(crate) fn objects(&self) -> &'a StoreObjects {
&self.inner.objects
}
pub fn tunables(&self) -> &dyn Tunables {
self.inner.tunables.as_ref()
}
pub fn engine(&self) -> &Engine {
&self.inner.engine
}
pub fn same(a: &Self, b: &Self) -> bool {
a.inner.engine.id() == b.inner.engine.id()
}
#[inline]
pub fn signal_handler(&self) -> Option<*const TrapHandlerFn<'static>> {
self.inner
.trap_handler
.as_ref()
.map(|handler| &*handler as *const _)
}
}
pub struct StoreMut<'a> {
pub(crate) inner: &'a mut StoreInner,
}
impl<'a> StoreMut<'a> {
pub fn tunables(&self) -> &dyn Tunables {
self.inner.tunables.as_ref()
}
pub fn engine(&self) -> &Engine {
&self.inner.engine
}
pub fn same(a: &Self, b: &Self) -> bool {
a.inner.engine.id() == b.inner.engine.id()
}
pub(crate) fn tunables_and_objects_mut(&mut self) -> (&dyn Tunables, &mut StoreObjects) {
(self.inner.tunables.as_ref(), &mut self.inner.objects)
}
pub(crate) fn as_raw(&self) -> *mut StoreInner {
self.inner as *const StoreInner as *mut StoreInner
}
pub(crate) unsafe fn from_raw(raw: *mut StoreInner) -> Self {
Self { inner: &mut *raw }
}
}
pub trait AsStoreRef {
fn as_store_ref(&self) -> StoreRef<'_>;
}
pub trait AsStoreMut: AsStoreRef {
fn as_store_mut(&mut self) -> StoreMut<'_>;
fn objects_mut(&mut self) -> &mut StoreObjects;
}
impl AsStoreRef for StoreRef<'_> {
fn as_store_ref(&self) -> StoreRef<'_> {
StoreRef { inner: self.inner }
}
}
impl AsStoreRef for StoreMut<'_> {
fn as_store_ref(&self) -> StoreRef<'_> {
StoreRef { inner: self.inner }
}
}
impl AsStoreMut for StoreMut<'_> {
fn as_store_mut(&mut self) -> StoreMut<'_> {
StoreMut { inner: self.inner }
}
fn objects_mut(&mut self) -> &mut StoreObjects {
&mut self.inner.objects
}
}
impl<T: AsStoreRef> AsStoreRef for &'_ T {
fn as_store_ref(&self) -> StoreRef<'_> {
T::as_store_ref(*self)
}
}
impl<T: AsStoreRef> AsStoreRef for &'_ mut T {
fn as_store_ref(&self) -> StoreRef<'_> {
T::as_store_ref(*self)
}
}
impl<T: AsStoreMut> AsStoreMut for &'_ mut T {
fn as_store_mut(&mut self) -> StoreMut<'_> {
T::as_store_mut(*self)
}
fn objects_mut(&mut self) -> &mut StoreObjects {
T::objects_mut(*self)
}
}