use crate::module::ModuleRegistry;
use crate::runtime::vm::{self, GcStore, VMStore};
use crate::store::StoreOpaque;
use crate::{StoreContext, StoreContextMut};
use core::num::NonZeroU64;
use core::ops::{Index, IndexMut};
use core::pin::Pin;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct InstanceId(u32);
wasmtime_environ::entity_impl!(InstanceId);
pub struct StoreData {
id: StoreId,
#[cfg(feature = "component-model")]
pub(crate) components: crate::component::ComponentStoreData,
}
impl StoreData {
pub fn new() -> StoreData {
StoreData {
id: StoreId::allocate(),
#[cfg(feature = "component-model")]
components: Default::default(),
}
}
pub fn id(&self) -> StoreId {
self.id
}
}
impl<I> Index<I> for StoreOpaque
where
StoreData: Index<I>,
{
type Output = <StoreData as Index<I>>::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
self.store_data.index(index)
}
}
impl<I> IndexMut<I> for StoreOpaque
where
StoreData: IndexMut<I>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.store_data.index_mut(index)
}
}
impl<I, T> Index<I> for StoreContext<'_, T>
where
StoreOpaque: Index<I>,
{
type Output = <StoreOpaque as Index<I>>::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
self.0.index(index)
}
}
impl<I, T> Index<I> for StoreContextMut<'_, T>
where
StoreOpaque: Index<I>,
{
type Output = <StoreOpaque as Index<I>>::Output;
#[inline]
fn index(&self, index: I) -> &Self::Output {
self.0.index(index)
}
}
impl<I, T> IndexMut<I> for StoreContextMut<'_, T>
where
StoreOpaque: IndexMut<I>,
{
#[inline]
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.0.index_mut(index)
}
}
impl<I> Index<I> for dyn VMStore + '_
where
StoreOpaque: Index<I>,
{
type Output = <StoreOpaque as Index<I>>::Output;
fn index(&self, index: I) -> &Self::Output {
self.store_opaque().index(index)
}
}
impl<I> IndexMut<I> for dyn VMStore + '_
where
StoreOpaque: IndexMut<I>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
self.store_opaque_mut().index_mut(index)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(transparent)] pub struct StoreId(NonZeroU64);
impl StoreId {
pub fn allocate() -> StoreId {
const OVERFLOW_THRESHOLD: u64 = 1 << 63;
#[cfg(target_has_atomic = "64")]
let id = {
use core::sync::atomic::{AtomicU64, Ordering::Relaxed};
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
let id = NEXT_ID.fetch_add(1, Relaxed);
if id > OVERFLOW_THRESHOLD {
NEXT_ID.store(OVERFLOW_THRESHOLD, Relaxed);
panic!("store id allocator overflow");
}
id
};
#[cfg(not(target_has_atomic = "64"))]
let id = {
use crate::sync::RwLock;
static NEXT_ID: RwLock<u64> = RwLock::new(0);
let mut lock = NEXT_ID.write();
if *lock > OVERFLOW_THRESHOLD {
panic!("store id allocator overflow");
}
let ret = *lock;
*lock += 1;
ret
};
StoreId(NonZeroU64::new(id + 1).unwrap())
}
#[inline]
pub fn assert_belongs_to(&self, store: StoreId) {
if *self == store {
return;
}
store_id_mismatch();
}
pub fn as_raw(&self) -> NonZeroU64 {
self.0
}
pub fn from_raw(id: NonZeroU64) -> StoreId {
StoreId(id)
}
}
#[cold]
fn store_id_mismatch() {
panic!("object used with the wrong store");
}
#[repr(C)] #[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct StoreInstanceId {
store_id: StoreId,
instance: InstanceId,
}
impl StoreInstanceId {
pub(crate) fn new(store_id: StoreId, instance: InstanceId) -> StoreInstanceId {
StoreInstanceId { store_id, instance }
}
#[inline]
pub fn assert_belongs_to(&self, store: StoreId) {
self.store_id.assert_belongs_to(store)
}
#[inline]
pub fn store_id(&self) -> StoreId {
self.store_id
}
#[inline]
pub(crate) fn instance(&self) -> InstanceId {
self.instance
}
#[inline]
pub(crate) fn get<'a>(&self, store: &'a StoreOpaque) -> &'a vm::Instance {
self.assert_belongs_to(store.id());
store.instance(self.instance)
}
#[inline]
pub(crate) fn get_mut<'a>(&self, store: &'a mut StoreOpaque) -> Pin<&'a mut vm::Instance> {
self.assert_belongs_to(store.id());
store.instance_mut(self.instance)
}
#[inline]
pub(crate) fn get_mut_and_module_registry<'a>(
&self,
store: &'a mut StoreOpaque,
) -> (Pin<&'a mut vm::Instance>, &'a ModuleRegistry) {
self.assert_belongs_to(store.id());
store.instance_and_module_registry_mut(self.instance)
}
#[inline]
pub(crate) fn get_with_gc_store_mut<'a>(
&self,
store: &'a mut StoreOpaque,
) -> (Option<&'a mut GcStore>, Pin<&'a mut vm::Instance>) {
self.assert_belongs_to(store.id());
store.optional_gc_store_and_instance_mut(self.instance)
}
}
impl Index<StoreInstanceId> for StoreOpaque {
type Output = vm::Instance;
#[inline]
fn index(&self, id: StoreInstanceId) -> &Self::Output {
id.get(self)
}
}