From a3fe372beb1a9636ed29f734dc5e9913fe1741b9 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 16 Aug 2019 17:36:11 -0700 Subject: [PATCH 1/2] Replace wasmer_runtime_code::memory::Atomic with std::sync::atomic atomics. This means we lose op_new(), op_weak() and proxy() from the interface. --- lib/runtime-core/src/memory/atomic.rs | 263 -------------------------- lib/runtime-core/src/memory/mod.rs | 2 - lib/runtime-core/src/memory/view.rs | 28 ++- lib/runtime/src/lib.rs | 2 +- 4 files changed, 21 insertions(+), 274 deletions(-) delete mode 100644 lib/runtime-core/src/memory/atomic.rs diff --git a/lib/runtime-core/src/memory/atomic.rs b/lib/runtime-core/src/memory/atomic.rs deleted file mode 100644 index f14415defd6..00000000000 --- a/lib/runtime-core/src/memory/atomic.rs +++ /dev/null @@ -1,263 +0,0 @@ -//! This is mostly copied from https://docs.rs/integer-atomics/1.0.2/src/integer_atomics/atomic.rs.html -//! Many thanks to "main()" for writing this. - -use std::cell::UnsafeCell; -use std::mem; -use std::num::Wrapping; -use std::ops::{Add, BitAnd, BitOr, BitXor, Sub}; -use std::panic::RefUnwindSafe; -use std::sync::atomic::{AtomicUsize, Ordering}; - -pub trait IntCast: - Copy - + Eq - + Add - + BitAnd - + BitOr - + BitXor - + Sub -{ - type Public: PartialEq + Copy; - - fn from(u: usize) -> Self; - fn to(self) -> usize; - - fn new(p: Self::Public) -> Self; - fn unwrap(self) -> Self::Public; -} - -macro_rules! intcast { - ($($type:ident)+) => { - $( - impl IntCast for $type { - type Public = $type; - - fn from(u: usize) -> Self { - u as $type - } - fn to(self) -> usize { - self as usize - } - - fn new(p: $type) -> Self { - p - } - - fn unwrap(self) -> $type { - self - } - } - )+ - } -} -intcast! { u8 i8 u16 i16 u32 i32 u64 i64 } - -#[repr(transparent)] -pub struct Atomic { - v: UnsafeCell>, -} - -impl Default for Atomic { - fn default() -> Self { - Self::new(T::default().unwrap()) - } -} - -// TODO: impl Debug - -unsafe impl Sync for Atomic {} -impl RefUnwindSafe for Atomic {} - -fn inject(a: usize, b: usize, offset: usize) -> usize { - let mask = ((1 << (mem::size_of::() * 8)) - 1) << offset; - (a & !mask) | (b << offset) -} - -// straight from libcore's atomic.rs -#[inline] -fn strongest_failure_ordering(order: Ordering) -> Ordering { - use self::Ordering::*; - match order { - Release => Relaxed, - Relaxed => Relaxed, - SeqCst => SeqCst, - Acquire => Acquire, - AcqRel => Acquire, - _ => unreachable!(), - } -} - -impl Atomic { - #[inline] - fn proxy(&self) -> (&AtomicUsize, usize) { - let ptr = self.v.get() as usize; - let aligned = ptr & !(mem::size_of::() - 1); - ( - unsafe { &*(aligned as *const AtomicUsize) }, - (ptr - aligned) * 8, - ) - } - - #[inline] - pub(super) fn new(v: T::Public) -> Self { - Atomic { - v: UnsafeCell::new(Wrapping(T::new(v))), - } - } - - #[inline] - pub fn get_mut(&mut self) -> &mut T::Public { - unsafe { &mut *(self.v.get() as *mut T::Public) } - } - - #[inline] - pub fn into_inner(self) -> T::Public { - self.v.into_inner().0.unwrap() - } - - #[inline] - pub fn load(&self, order: Ordering) -> T::Public { - let (p, o) = self.proxy(); - T::from(p.load(order) >> o).unwrap() - } - - #[inline] - fn op Option>(&self, f: F, order: Ordering) -> T::Public { - self.op_new(f, order, strongest_failure_ordering(order)) - } - - #[inline] - fn op_new Option>( - &self, - f: F, - success: Ordering, - failure: Ordering, - ) -> T::Public { - let (p, o) = self.proxy(); - let mut old = p.load(Ordering::Relaxed); - loop { - let old_t = T::from(old >> o); - let new_t = match f(old_t) { - Some(x) => x, - None => return old_t.unwrap(), - }; - - match Self::op_weak(p, o, old, new_t, success, failure) { - Ok(()) => return T::from(old >> o).unwrap(), - Err(prev) => old = prev, - }; - } - } - - #[inline] - fn op_weak( - p: &AtomicUsize, - o: usize, - old: usize, - new_t: T, - success: Ordering, - failure: Ordering, - ) -> Result<(), usize> { - let new = inject::(old, new_t.to(), o); - p.compare_exchange_weak(old, new, success, failure) - .map(|_| ()) - } - - #[inline] - pub fn store(&self, val: T::Public, order: Ordering) { - self.op(|_| Some(T::new(val)), order); - } - - #[inline] - pub fn swap(&self, val: T::Public, order: Ordering) -> T::Public { - self.op(|_| Some(T::new(val)), order) - } - - #[inline] - pub fn compare_and_swap( - &self, - current: T::Public, - new: T::Public, - order: Ordering, - ) -> T::Public { - self.op( - |x| { - if x == T::new(current) { - Some(T::new(new)) - } else { - None - } - }, - order, - ) - } - - #[inline] - pub fn compare_exchange( - &self, - current: T::Public, - new: T::Public, - success: Ordering, - failure: Ordering, - ) -> Result { - match self.op_new( - |x| { - if x == T::new(current) { - Some(T::new(new)) - } else { - None - } - }, - success, - failure, - ) { - x if x == current => Ok(x), - x => Err(x), - } - } - - #[inline] - pub fn compare_exchange_weak( - &self, - current: T::Public, - new: T::Public, - success: Ordering, - failure: Ordering, - ) -> Result { - let (p, o) = self.proxy(); - let old = p.load(Ordering::Relaxed); - let old_t = T::from(old >> o).unwrap(); - if old_t != current { - return Err(old_t); - } - - Self::op_weak(p, o, old, T::new(new), success, failure) - .map(|()| current) - .map_err(|x| T::from(x >> o).unwrap()) - } - - #[inline] - pub fn fetch_add(&self, val: T::Public, order: Ordering) -> T::Public { - self.op(|x| Some(x + T::new(val)), order) - } - - #[inline] - pub fn fetch_sub(&self, val: T::Public, order: Ordering) -> T::Public { - self.op(|x| Some(x - T::new(val)), order) - } - - #[inline] - pub fn fetch_and(&self, val: T::Public, order: Ordering) -> T::Public { - self.op(|x| Some(x & T::new(val)), order) - } - - #[inline] - pub fn fetch_or(&self, val: T::Public, order: Ordering) -> T::Public { - self.op(|x| Some(x | T::new(val)), order) - } - - #[inline] - pub fn fetch_xor(&self, val: T::Public, order: Ordering) -> T::Public { - self.op(|x| Some(x ^ T::new(val)), order) - } -} diff --git a/lib/runtime-core/src/memory/mod.rs b/lib/runtime-core/src/memory/mod.rs index f618c33d816..d7c32dc98bb 100644 --- a/lib/runtime-core/src/memory/mod.rs +++ b/lib/runtime-core/src/memory/mod.rs @@ -14,12 +14,10 @@ use std::{ rc::Rc, }; -pub use self::atomic::Atomic; pub use self::dynamic::DynamicMemory; pub use self::static_::{SharedStaticMemory, StaticMemory}; pub use self::view::{Atomically, MemoryView}; -mod atomic; mod dynamic; pub mod ptr; mod static_; diff --git a/lib/runtime-core/src/memory/view.rs b/lib/runtime-core/src/memory/view.rs index 3376c6e17ca..802c26903a2 100644 --- a/lib/runtime-core/src/memory/view.rs +++ b/lib/runtime-core/src/memory/view.rs @@ -1,7 +1,19 @@ -use super::atomic::{Atomic, IntCast}; use crate::types::ValueType; use std::{cell::Cell, marker::PhantomData, ops::Deref, slice}; +use std::sync::atomic::{AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicU8, AtomicU16, AtomicU32, AtomicU64}; + +pub trait Atomic { type Output; } +impl Atomic for i8 { type Output = AtomicI8; } +impl Atomic for i16 { type Output = AtomicI16; } +impl Atomic for i32 { type Output = AtomicI32; } +impl Atomic for i64 { type Output = AtomicI64; } +impl Atomic for u8 { type Output = AtomicU8; } +impl Atomic for u16 { type Output = AtomicU16; } +impl Atomic for u32 { type Output = AtomicU32; } +impl Atomic for u64 { type Output = AtomicU64; } +impl Atomic for f32 { type Output = AtomicU32; } +impl Atomic for f64 { type Output = AtomicU64; } pub trait Atomicity {} pub struct Atomically; @@ -28,10 +40,10 @@ where } } -impl<'a, T: IntCast> MemoryView<'a, T, NonAtomically> { - pub fn atomically(&self) -> MemoryView<'a, T, Atomically> { +impl<'a, T: Atomic> MemoryView<'a, T> { + pub fn atomically(&self) -> MemoryView<'a, T::Output, Atomically> { MemoryView { - ptr: self.ptr, + ptr: self.ptr as *mut T::Output, length: self.length, _phantom: PhantomData, } @@ -45,9 +57,9 @@ impl<'a, T> Deref for MemoryView<'a, T, NonAtomically> { } } -impl<'a, T: IntCast> Deref for MemoryView<'a, T, Atomically> { - type Target = [Atomic]; - fn deref(&self) -> &[Atomic] { - unsafe { slice::from_raw_parts(self.ptr as *const Atomic, self.length) } +impl<'a, T> Deref for MemoryView<'a, T, Atomically> { + type Target = [T]; + fn deref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.ptr as *const T, self.length) } } } diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 78c6235c8cc..5b3ba852689 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -100,7 +100,7 @@ pub use wasmer_runtime_core::{compile_with, validate}; pub use wasmer_runtime_core::{func, imports}; pub mod memory { - pub use wasmer_runtime_core::memory::{Atomic, Atomically, Memory, MemoryView}; + pub use wasmer_runtime_core::memory::{Atomically, Memory, MemoryView}; } pub mod wasm { From 3040ec90ad87bbcff49735fcec2f176f81d6c776 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Fri, 16 Aug 2019 18:00:20 -0700 Subject: [PATCH 2/2] cargo fmt --- lib/runtime-core/src/memory/view.rs | 48 +++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/lib/runtime-core/src/memory/view.rs b/lib/runtime-core/src/memory/view.rs index 802c26903a2..4dbaa5bd52d 100644 --- a/lib/runtime-core/src/memory/view.rs +++ b/lib/runtime-core/src/memory/view.rs @@ -1,19 +1,43 @@ use crate::types::ValueType; +use std::sync::atomic::{ + AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicU16, AtomicU32, AtomicU64, AtomicU8, +}; use std::{cell::Cell, marker::PhantomData, ops::Deref, slice}; -use std::sync::atomic::{AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicU8, AtomicU16, AtomicU32, AtomicU64}; -pub trait Atomic { type Output; } -impl Atomic for i8 { type Output = AtomicI8; } -impl Atomic for i16 { type Output = AtomicI16; } -impl Atomic for i32 { type Output = AtomicI32; } -impl Atomic for i64 { type Output = AtomicI64; } -impl Atomic for u8 { type Output = AtomicU8; } -impl Atomic for u16 { type Output = AtomicU16; } -impl Atomic for u32 { type Output = AtomicU32; } -impl Atomic for u64 { type Output = AtomicU64; } -impl Atomic for f32 { type Output = AtomicU32; } -impl Atomic for f64 { type Output = AtomicU64; } +pub trait Atomic { + type Output; +} +impl Atomic for i8 { + type Output = AtomicI8; +} +impl Atomic for i16 { + type Output = AtomicI16; +} +impl Atomic for i32 { + type Output = AtomicI32; +} +impl Atomic for i64 { + type Output = AtomicI64; +} +impl Atomic for u8 { + type Output = AtomicU8; +} +impl Atomic for u16 { + type Output = AtomicU16; +} +impl Atomic for u32 { + type Output = AtomicU32; +} +impl Atomic for u64 { + type Output = AtomicU64; +} +impl Atomic for f32 { + type Output = AtomicU32; +} +impl Atomic for f64 { + type Output = AtomicU64; +} pub trait Atomicity {} pub struct Atomically;