Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ContextObjects to Store #3011

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ default-llvm = ["default-compiler", "llvm"]
engine = ["sys"]
universal = [
"engine",
"wasmer-compiler/universal_engine"
]
default-engine = []
default-universal = [
Expand Down
120 changes: 48 additions & 72 deletions lib/api/src/js/context.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
#![allow(dead_code)]
use crate::Store;

/// We require the context to have a fixed memory address for its lifetime since
/// various bits of the VM have raw pointers that point back to it. Hence we
/// wrap the actual context in a box.
pub(crate) struct ContextInner<T> {
pub(crate) objects: ContextObjects,
pub(crate) store: Store,
pub(crate) objects: StoreObjects,
pub(crate) data: T,
}

Expand Down Expand Up @@ -35,11 +31,10 @@ pub struct Context<T> {
impl<T> Context<T> {
/// Creates a new context with the given host state.
// TODO: Eliminate the Store type and move its functionality into Engine.
pub fn new(store: &Store, data: T) -> Self {
pub fn new(data: T) -> Self {
Self {
inner: Box::new(ContextInner {
objects: Default::default(),
store: store.clone(),
data,
}),
}
Expand All @@ -59,11 +54,6 @@ impl<T> Context<T> {
pub fn into_data(self) -> T {
self.inner.data
}

/// Returns a reference to the `Store` of this context.
pub fn store(&self) -> &Store {
&self.inner.store
}
}

/// A temporary handle to a [`Context`].
Expand All @@ -76,15 +66,6 @@ impl<'a, T> ContextRef<'a, T> {
pub fn data(&self) -> &'a T {
&self.inner.data
}

/// Returns a reference to the `Store` of this context.
pub fn store(&self) -> &Store {
&self.inner.store
}

pub(crate) fn objects(&self) -> &'a ContextObjects {
&self.inner.objects
}
}

/// A temporary handle to a [`Context`].
Expand All @@ -103,15 +84,10 @@ impl<T> ContextMut<'_, T> {
&mut self.inner.data
}

pub(crate) fn objects_mut(&mut self) -> &mut ContextObjects {
pub(crate) fn objects_mut(&mut self) -> &mut StoreObjects {
&mut self.inner.objects
}

/// Returns a reference to the `Store` of this context.
pub fn store(&self) -> &Store {
&self.inner.store
}

/// Returns the raw pointer of the context
pub(crate) fn as_raw(&self) -> *mut ContextInner<T> {
self.inner as *const ContextInner<T> as *mut ContextInner<T>
Expand Down Expand Up @@ -209,9 +185,9 @@ mod objects {
/// context. This is used to check that a handle is always used with the
/// correct context.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct ContextId(NonZeroU64);
pub struct StoreId(NonZeroU64);

impl Default for ContextId {
impl Default for StoreId {
// Allocates a unique ID for a new context.
fn default() -> Self {
// No overflow checking is needed here: overflowing this would take
Expand All @@ -223,19 +199,19 @@ mod objects {

/// Trait to represent an object managed by a context. This is implemented on
/// the VM types managed by the context.
pub trait ContextObject: Sized {
fn list(ctx: &ContextObjects) -> &Vec<Self>;
fn list_mut(ctx: &mut ContextObjects) -> &mut Vec<Self>;
pub trait StoreObject: Sized {
fn list(ctx: &StoreObjects) -> &Vec<Self>;
fn list_mut(ctx: &mut StoreObjects) -> &mut Vec<Self>;
}

macro_rules! impl_context_object {
($($field:ident => $ty:ty,)*) => {
$(
impl ContextObject for $ty {
fn list(ctx: &ContextObjects) -> &Vec<Self> {
impl StoreObject for $ty {
fn list(ctx: &StoreObjects) -> &Vec<Self> {
&ctx.$field
}
fn list_mut(ctx: &mut ContextObjects) -> &mut Vec<Self> {
fn list_mut(ctx: &mut StoreObjects) -> &mut Vec<Self> {
&mut ctx.$field
}
}
Expand All @@ -253,28 +229,28 @@ mod objects {

/// Set of objects managed by a context.
#[derive(Default)]
pub struct ContextObjects {
id: ContextId,
pub struct StoreObjects {
id: StoreId,
memories: Vec<VMMemory>,
tables: Vec<VMTable>,
globals: Vec<VMGlobal>,
functions: Vec<VMFunction>,
instances: Vec<js_sys::WebAssembly::Instance>,
}

impl ContextObjects {
impl StoreObjects {
/// Returns the ID of this context.
pub fn id(&self) -> ContextId {
pub fn id(&self) -> StoreId {
self.id
}

/// Returns a pair of mutable references from two handles.
///
/// Panics if both handles point to the same object.
pub fn get_2_mut<T: ContextObject>(
pub fn get_2_mut<T: StoreObject>(
&mut self,
a: InternalContextHandle<T>,
b: InternalContextHandle<T>,
a: InternalStoreHandle<T>,
b: InternalStoreHandle<T>,
) -> (&mut T, &mut T) {
assert_ne!(a.index(), b.index());
let list = T::list_mut(self);
Expand All @@ -292,17 +268,17 @@ mod objects {
///
/// Internally this is just an integer index into a context. A reference to the
/// context must be passed in separately to access the actual object.
pub struct ContextHandle<T> {
id: ContextId,
internal: InternalContextHandle<T>,
pub struct StoreHandle<T> {
id: StoreId,
internal: InternalStoreHandle<T>,
}

impl<T> core::cmp::PartialEq for ContextHandle<T> {
impl<T> core::cmp::PartialEq for StoreHandle<T> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<T> Clone for ContextHandle<T> {
impl<T> Clone for StoreHandle<T> {
fn clone(&self) -> Self {
Self {
id: self.id,
Expand All @@ -311,90 +287,90 @@ mod objects {
}
}

impl<T: ContextObject> fmt::Debug for ContextHandle<T> {
impl<T: StoreObject> fmt::Debug for StoreHandle<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ContextHandle")
f.debug_struct("StoreHandle")
.field("id", &self.id)
.field("internal", &self.internal.index())
.finish()
}
}

impl<T: ContextObject> ContextHandle<T> {
impl<T: StoreObject> StoreHandle<T> {
/// Moves the given object into a context and returns a handle to it.
pub fn new(ctx: &mut ContextObjects, val: T) -> Self {
pub fn new(ctx: &mut StoreObjects, val: T) -> Self {
Self {
id: ctx.id,
internal: InternalContextHandle::new(ctx, val),
internal: InternalStoreHandle::new(ctx, val),
}
}

/// Returns a reference to the object that this handle points to.
pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T {
pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T {
assert_eq!(self.id, ctx.id, "object used with the wrong context");
self.internal.get(ctx)
}

/// Returns a mutable reference to the object that this handle points to.
pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T {
pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T {
assert_eq!(self.id, ctx.id, "object used with the wrong context");
self.internal.get_mut(ctx)
}

/// Returns the internal handle contains within this handle.
pub fn internal_handle(&self) -> InternalContextHandle<T> {
pub fn internal_handle(&self) -> InternalStoreHandle<T> {
self.internal
}

/// Returns the ID of the context associated with the handle.
pub fn context_id(&self) -> ContextId {
pub fn store_id(&self) -> StoreId {
self.id
}

/// Constructs a `ContextHandle` from a `ContextId` and an `InternalContextHandle`.
/// Constructs a `StoreHandle` from a `StoreId` and an `InternalStoreHandle`.
///
/// # Safety
/// Handling `InternalContextHandle` values is unsafe because they do not track context ID.
pub unsafe fn from_internal(id: ContextId, internal: InternalContextHandle<T>) -> Self {
/// Handling `InternalStoreHandle` values is unsafe because they do not track context ID.
pub unsafe fn from_internal(id: StoreId, internal: InternalStoreHandle<T>) -> Self {
Self { id, internal }
}
}

/// Internal handle to an object owned by the current context.
///
/// Unlike `ContextHandle` this does not track the context ID: it is only
/// Unlike `StoreHandle` this does not track the context ID: it is only
/// intended to be used within objects already owned by a context.
#[repr(transparent)]
pub struct InternalContextHandle<T> {
// Use a NonZero here to reduce the size of Option<InternalContextHandle>.
pub struct InternalStoreHandle<T> {
// Use a NonZero here to reduce the size of Option<InternalStoreHandle>.
idx: NonZeroUsize,
marker: PhantomData<fn() -> T>,
}

impl<T> Clone for InternalContextHandle<T> {
impl<T> Clone for InternalStoreHandle<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for InternalContextHandle<T> {}
impl<T> Copy for InternalStoreHandle<T> {}

impl<T> fmt::Debug for InternalContextHandle<T> {
impl<T> fmt::Debug for InternalStoreHandle<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("InternalContextHandle")
f.debug_struct("InternalStoreHandle")
.field("idx", &self.idx)
.finish()
}
}
impl<T> PartialEq for InternalContextHandle<T> {
impl<T> PartialEq for InternalStoreHandle<T> {
fn eq(&self, other: &Self) -> bool {
self.idx == other.idx
}
}
impl<T> Eq for InternalContextHandle<T> {}
impl<T> Eq for InternalStoreHandle<T> {}

impl<T: ContextObject> InternalContextHandle<T> {
impl<T: StoreObject> InternalStoreHandle<T> {
/// Moves the given object into a context and returns a handle to it.
pub fn new(ctx: &mut ContextObjects, val: T) -> Self {
pub fn new(ctx: &mut StoreObjects, val: T) -> Self {
let list = T::list_mut(ctx);
let idx = NonZeroUsize::new(list.len() + 1).unwrap();
list.push(val);
Expand All @@ -405,12 +381,12 @@ mod objects {
}

/// Returns a reference to the object that this handle points to.
pub fn get<'a>(&self, ctx: &'a ContextObjects) -> &'a T {
pub fn get<'a>(&self, ctx: &'a StoreObjects) -> &'a T {
&T::list(ctx)[self.idx.get() - 1]
}

/// Returns a mutable reference to the object that this handle points to.
pub fn get_mut<'a>(&self, ctx: &'a mut ContextObjects) -> &'a mut T {
pub fn get_mut<'a>(&self, ctx: &'a mut StoreObjects) -> &'a mut T {
&mut T::list_mut(ctx)[self.idx.get() - 1]
}

Expand Down
Loading