unc_vm_vm/instance/ref.rs
1use super::Instance;
2use std::alloc::Layout;
3use std::convert::TryFrom;
4use std::ptr::{self, NonNull};
5use std::sync::{Arc, Weak};
6
7/// Dynamic instance allocation.
8///
9/// This structure has a C representation because `Instance` is
10/// dynamically-sized, and the `instance` field must be last.
11///
12/// This `InstanceRef` must be freed with [`InstanceInner::deallocate_instance`]
13/// if and only if it has been set correctly. The `Drop` implementation of
14/// [`InstanceInner`] calls its `deallocate_instance` method without
15/// checking if this property holds, only when `Self.strong` is equal to 1.
16#[derive(Debug)]
17#[repr(C)]
18struct InstanceInner {
19 /// The layout of `Instance` (which can vary).
20 instance_layout: Layout,
21
22 /// The `Instance` itself. It must be the last field of
23 /// `InstanceRef` since `Instance` is dyamically-sized.
24 ///
25 /// `Instance` must not be dropped manually by Rust, because it's
26 /// allocated manually with `alloc` and a specific layout (Rust
27 /// would be able to drop `Instance` itself but it will imply a
28 /// memory leak because of `alloc`).
29 ///
30 /// No one in the code has a copy of the `Instance`'s
31 /// pointer. `Self` is the only one.
32 instance: NonNull<Instance>,
33}
34
35impl InstanceInner {
36 /// Deallocate `Instance`.
37 ///
38 /// # Safety
39 ///
40 /// `Self.instance` must be correctly set and filled before being
41 /// dropped and deallocated.
42 unsafe fn deallocate_instance(&mut self) {
43 let instance_ptr = self.instance.as_ptr();
44
45 ptr::drop_in_place(instance_ptr);
46 std::alloc::dealloc(instance_ptr as *mut u8, self.instance_layout);
47 }
48
49 /// Get a reference to the `Instance`.
50 #[inline]
51 pub(crate) fn as_ref(&self) -> &Instance {
52 // SAFETY: The pointer is properly aligned, it is
53 // “dereferencable”, it points to an initialized memory of
54 // `Instance`, and the reference has the lifetime `'a`.
55 unsafe { self.instance.as_ref() }
56 }
57
58 #[inline]
59 pub(super) fn as_mut(&mut self) -> &mut Instance {
60 unsafe { self.instance.as_mut() }
61 }
62}
63
64impl PartialEq for InstanceInner {
65 /// Two `InstanceInner` are equal if and only if
66 /// `Self.instance` points to the same location.
67 fn eq(&self, other: &Self) -> bool {
68 self.instance == other.instance
69 }
70}
71
72impl Drop for InstanceInner {
73 /// Drop the `InstanceInner`.
74 fn drop(&mut self) {
75 unsafe { Self::deallocate_instance(self) };
76 }
77}
78
79// TODO: These implementations have been added to enable instances to contain `Arc`s, however it
80// isn’t exactly clear that the `InstanceInner` contents are `Send` or `Sync`, thus effectively
81// lying to the compiler. Fortunately in actual use this is not a big deal as the unc runtime is
82// single-threaded anyway (and `Arc` is only necessary to facilitate caching of the loaded
83// modules IIRC; an attempt to remove this cache has been made in the past, but had to be
84// restored.)
85unsafe impl Send for InstanceInner {}
86unsafe impl Sync for InstanceInner {}
87
88/// An `InstanceRef` is responsible to properly deallocate,
89/// and to give access to an `Instance`, in such a way that `Instance`
90/// is unique, can be shared, safely, across threads, without
91/// duplicating the pointer in multiple locations. `InstanceRef`
92/// must be the only “owner” of an `Instance`.
93///
94/// Consequently, one must not share `Instance` but
95/// `InstanceRef`. It acts like an Atomically Reference Counter
96/// to `Instance`. In short, `InstanceRef` is roughly a
97/// simplified version of `std::sync::Arc`.
98///
99/// Note for the curious reader: [`InstanceAllocator::new`]
100/// and [`InstanceHandle::new`] will respectively allocate a proper
101/// `Instance` and will fill it correctly.
102///
103/// A little bit of background: The initial goal was to be able to
104/// share an [`Instance`] between an [`InstanceHandle`] and the module
105/// exports, so that one can drop a [`InstanceHandle`] but still being
106/// able to use the exports properly.
107#[derive(Debug, PartialEq, Clone)]
108pub struct InstanceRef(Arc<InstanceInner>);
109
110impl InstanceRef {
111 /// Create a new `InstanceRef`. It allocates nothing. It fills
112 /// nothing. The `Instance` must be already valid and
113 /// filled.
114 ///
115 /// # Safety
116 ///
117 /// `instance` must a non-null, non-dangling, properly aligned,
118 /// and correctly initialized pointer to `Instance`. See
119 /// [`InstanceAllocator`] for an example of how to correctly use
120 /// this API.
121 pub(super) unsafe fn new(instance: NonNull<Instance>, instance_layout: Layout) -> Self {
122 Self(Arc::new(InstanceInner { instance_layout, instance }))
123 }
124
125 /// Get a reference to the `Instance`.
126 #[inline]
127 pub fn as_ref(&self) -> &Instance {
128 (&*self.0).as_ref()
129 }
130
131 /// Only succeeds if ref count is 1.
132 #[inline]
133 pub(super) fn as_mut(&mut self) -> Option<&mut Instance> {
134 Some(Arc::get_mut(&mut self.0)?.as_mut())
135 }
136
137 /// Like [`InstanceRef::as_mut`] but always succeeds.
138 /// May cause undefined behavior if used improperly.
139 ///
140 /// # Safety
141 /// It is the caller's responsibility to ensure exclusivity and synchronization of the
142 /// instance before calling this function. No other pointers to any Instance data
143 /// should be dereferenced for the lifetime of the returned `&mut Instance`.
144 #[inline]
145 pub(super) unsafe fn as_mut_unchecked(&mut self) -> &mut Instance {
146 let ptr: *mut InstanceInner = Arc::as_ptr(&self.0) as *mut _;
147 (&mut *ptr).as_mut()
148 }
149}
150
151/// A weak instance ref. This type does not keep the underlying `Instance` alive
152/// but can be converted into a full `InstanceRef` if the underlying `Instance` hasn't
153/// been deallocated.
154#[derive(Debug, Clone)]
155pub struct WeakInstanceRef(Weak<InstanceInner>);
156
157impl PartialEq for WeakInstanceRef {
158 fn eq(&self, other: &Self) -> bool {
159 self.0.ptr_eq(&other.0)
160 }
161}
162
163impl WeakInstanceRef {
164 /// Try to convert into a strong, `InstanceRef`.
165 pub fn upgrade(&self) -> Option<InstanceRef> {
166 let inner = self.0.upgrade()?;
167 Some(InstanceRef(inner))
168 }
169}
170
171/// An `InstanceRef` that may or may not be keeping the `Instance` alive.
172///
173/// This type is useful for types that conditionally must keep / not keep the
174/// underlying `Instance` alive. For example, to prevent cycles in `WasmerEnv`s.
175#[derive(Debug, Clone, PartialEq)]
176pub enum WeakOrStrongInstanceRef {
177 /// A weak instance ref.
178 Weak(WeakInstanceRef),
179 /// A strong instance ref.
180 Strong(InstanceRef),
181}
182
183impl WeakOrStrongInstanceRef {
184 /// Tries to upgrade weak references to a strong reference, returning None
185 /// if it can't be done.
186 pub fn upgrade(&self) -> Option<Self> {
187 match self {
188 Self::Weak(weak) => weak.upgrade().map(Self::Strong),
189 Self::Strong(strong) => Some(Self::Strong(strong.clone())),
190 }
191 }
192
193 /// Clones self into a weak reference.
194 pub fn downgrade(&self) -> Self {
195 match self {
196 Self::Weak(weak) => Self::Weak(weak.clone()),
197 Self::Strong(strong) => Self::Weak(WeakInstanceRef(Arc::downgrade(&strong.0))),
198 }
199 }
200}
201
202impl TryFrom<WeakOrStrongInstanceRef> for InstanceRef {
203 type Error = &'static str;
204 fn try_from(value: WeakOrStrongInstanceRef) -> Result<Self, Self::Error> {
205 match value {
206 WeakOrStrongInstanceRef::Strong(strong) => Ok(strong),
207 WeakOrStrongInstanceRef::Weak(weak) => {
208 weak.upgrade().ok_or("Failed to upgrade weak reference")
209 }
210 }
211 }
212}
213
214impl From<WeakOrStrongInstanceRef> for WeakInstanceRef {
215 fn from(value: WeakOrStrongInstanceRef) -> Self {
216 match value {
217 WeakOrStrongInstanceRef::Strong(strong) => Self(Arc::downgrade(&strong.0)),
218 WeakOrStrongInstanceRef::Weak(weak) => weak,
219 }
220 }
221}
222
223impl From<WeakInstanceRef> for WeakOrStrongInstanceRef {
224 fn from(value: WeakInstanceRef) -> Self {
225 Self::Weak(value)
226 }
227}
228
229impl From<InstanceRef> for WeakOrStrongInstanceRef {
230 fn from(value: InstanceRef) -> Self {
231 Self::Strong(value)
232 }
233}