Merge branch 'master' into feature/fix-singlepass-panic-no-functions

This commit is contained in:
Brandon Fish 2019-08-19 09:24:55 -06:00 committed by GitHub
commit 38b1e3d25e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 275 deletions

View File

@ -1,6 +1,6 @@
<p align="center">
<a href="https://wasmer.io" target="_blank" rel="noopener noreferrer">
<img width="400" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo">
<img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo">
</a>
</p>

View File

@ -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<Output = Self>
+ BitAnd<Output = Self>
+ BitOr<Output = Self>
+ BitXor<Output = Self>
+ Sub<Output = Self>
{
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<T> {
v: UnsafeCell<Wrapping<T>>,
}
impl<T: Default + IntCast> Default for Atomic<T> {
fn default() -> Self {
Self::new(T::default().unwrap())
}
}
// TODO: impl Debug
unsafe impl<T> Sync for Atomic<T> {}
impl<T> RefUnwindSafe for Atomic<T> {}
fn inject<T>(a: usize, b: usize, offset: usize) -> usize {
let mask = ((1 << (mem::size_of::<T>() * 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<T: IntCast> Atomic<T> {
#[inline]
fn proxy(&self) -> (&AtomicUsize, usize) {
let ptr = self.v.get() as usize;
let aligned = ptr & !(mem::size_of::<usize>() - 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<F: Fn(T) -> Option<T>>(&self, f: F, order: Ordering) -> T::Public {
self.op_new(f, order, strongest_failure_ordering(order))
}
#[inline]
fn op_new<F: Fn(T) -> Option<T>>(
&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::<T>(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<T::Public, T::Public> {
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<T::Public, T::Public> {
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)
}
}

View File

@ -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_;

View File

@ -1,8 +1,44 @@
use super::atomic::{Atomic, IntCast};
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};
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;
impl Atomicity for Atomically {}
@ -28,10 +64,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 +81,9 @@ impl<'a, T> Deref for MemoryView<'a, T, NonAtomically> {
}
}
impl<'a, T: IntCast> Deref for MemoryView<'a, T, Atomically> {
type Target = [Atomic<T>];
fn deref(&self) -> &[Atomic<T>] {
unsafe { slice::from_raw_parts(self.ptr as *const Atomic<T>, 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) }
}
}

View File

@ -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 {

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

After

Width:  |  Height:  |  Size: 27 KiB