mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-26 07:01:33 +00:00
Merge branch 'master' into feat-runtime-core-wasm-extern-type-macros
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
## **[Unreleased]**
|
## **[Unreleased]**
|
||||||
|
|
||||||
|
- [#1228](https://github.com/wasmerio/wasmer/pull/1228) Singlepass cleanup: Resolve several FIXMEs and remove protect_unix.
|
||||||
- [#1218](https://github.com/wasmerio/wasmer/pull/1218) Enable Cranelift verifier in debug mode. Fix bug with table indices being the wrong type.
|
- [#1218](https://github.com/wasmerio/wasmer/pull/1218) Enable Cranelift verifier in debug mode. Fix bug with table indices being the wrong type.
|
||||||
- [#787](https://github.com/wasmerio/wasmer/pull/787) New crate `wasmer-interface-types` to implement WebAssembly Interface Types.
|
- [#787](https://github.com/wasmerio/wasmer/pull/787) New crate `wasmer-interface-types` to implement WebAssembly Interface Types.
|
||||||
- [#1213](https://github.com/wasmerio/wasmer/pull/1213) Fixed WASI `fdstat` to detect `isatty` properly.
|
- [#1213](https://github.com/wasmerio/wasmer/pull/1213) Fixed WASI `fdstat` to detect `isatty` properly.
|
||||||
|
32
lib/interface-types/README.md
Normal file
32
lib/interface-types/README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="https://wasmer.io" target="_blank" rel="noopener noreferrer">
|
||||||
|
<img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://dev.azure.com/wasmerio/wasmer/_build/latest?definitionId=3&branchName=master">
|
||||||
|
<img src="https://img.shields.io/azure-devops/build/wasmerio/wasmer/3.svg?style=flat-square" alt="Build Status">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE">
|
||||||
|
<img src="https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square" alt="License">
|
||||||
|
</a>
|
||||||
|
<a href="https://spectrum.chat/wasmer">
|
||||||
|
<img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community">
|
||||||
|
</a>
|
||||||
|
<a href="https://crates.io/crates/wasmer-interface-types">
|
||||||
|
<img src="https://img.shields.io/crates/d/wasmer-interface-types.svg?style=flat-square" alt="Number of downloads from crates.io">
|
||||||
|
</a>
|
||||||
|
<a href="https://docs.rs/wasmer-interface-types">
|
||||||
|
<img src="https://docs.rs/wasmer-interface-types/badge.svg" alt="Read our API documentation">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
# Wasmer Interface Types
|
||||||
|
|
||||||
|
Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully
|
||||||
|
compatible with WASI, Emscripten, Rust and Go. [Learn
|
||||||
|
more](https://github.com/wasmerio/wasmer).
|
||||||
|
|
||||||
|
This crate is an implementation of [the living WebAssembly Interface
|
||||||
|
Types standard](https://github.com/WebAssembly/interface-types).
|
@ -310,6 +310,7 @@ macro_rules! impl_traits {
|
|||||||
where
|
where
|
||||||
$( $x: WasmExternType ),*;
|
$( $x: WasmExternType ),*;
|
||||||
|
|
||||||
|
#[allow(unused_parens)]
|
||||||
impl< $( $x ),* > WasmTypeList for ( $( $x ),* )
|
impl< $( $x ),* > WasmTypeList for ( $( $x ),* )
|
||||||
where
|
where
|
||||||
$( $x: WasmExternType ),*
|
$( $x: WasmExternType ),*
|
||||||
@ -380,6 +381,7 @@ macro_rules! impl_traits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_parens)]
|
||||||
impl< $( $x, )* Rets, Trap, FN > ExternalFunction<ExplicitVmCtx, ( $( $x ),* ), Rets> for FN
|
impl< $( $x, )* Rets, Trap, FN > ExternalFunction<ExplicitVmCtx, ( $( $x ),* ), Rets> for FN
|
||||||
where
|
where
|
||||||
$( $x: WasmExternType, )*
|
$( $x: WasmExternType, )*
|
||||||
@ -495,6 +497,7 @@ macro_rules! impl_traits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_parens)]
|
||||||
impl< $( $x, )* Rets, Trap, FN > ExternalFunction<ImplicitVmCtx, ( $( $x ),* ), Rets> for FN
|
impl< $( $x, )* Rets, Trap, FN > ExternalFunction<ImplicitVmCtx, ( $( $x ),* ), Rets> for FN
|
||||||
where
|
where
|
||||||
$( $x: WasmExternType, )*
|
$( $x: WasmExternType, )*
|
||||||
@ -607,6 +610,7 @@ macro_rules! impl_traits {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_parens)]
|
||||||
impl<'a $( , $x )*, Rets> Func<'a, ( $( $x ),* ), Rets, Wasm>
|
impl<'a $( , $x )*, Rets> Func<'a, ( $( $x ),* ), Rets, Wasm>
|
||||||
where
|
where
|
||||||
$( $x: WasmExternType, )*
|
$( $x: WasmExternType, )*
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
use crate::emitter_x64::*;
|
use crate::emitter_x64::*;
|
||||||
use crate::machine::*;
|
use crate::machine::*;
|
||||||
use crate::protect_unix;
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use dynasmrt::aarch64::Assembler;
|
use dynasmrt::aarch64::Assembler;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@ -28,7 +27,7 @@ use wasmer_runtime_core::{
|
|||||||
},
|
},
|
||||||
cache::{Artifact, Error as CacheError},
|
cache::{Artifact, Error as CacheError},
|
||||||
codegen::*,
|
codegen::*,
|
||||||
fault::raw::register_preservation_trampoline,
|
fault::{self, raw::register_preservation_trampoline},
|
||||||
loader::CodeMemory,
|
loader::CodeMemory,
|
||||||
memory::MemoryType,
|
memory::MemoryType,
|
||||||
module::{ModuleInfo, ModuleInner},
|
module::{ModuleInfo, ModuleInner},
|
||||||
@ -369,6 +368,11 @@ impl RunnableModule for X64ExecutionContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
|
fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
|
||||||
|
// Correctly unwinding from `catch_unsafe_unwind` on hardware exceptions depends
|
||||||
|
// on the signal handlers being installed. Here we call `ensure_sighandler` "statically"
|
||||||
|
// outside `invoke()`.
|
||||||
|
fault::ensure_sighandler();
|
||||||
|
|
||||||
unsafe extern "C" fn invoke(
|
unsafe extern "C" fn invoke(
|
||||||
_trampoline: Trampoline,
|
_trampoline: Trampoline,
|
||||||
ctx: *mut vm::Ctx,
|
ctx: *mut vm::Ctx,
|
||||||
@ -383,8 +387,9 @@ impl RunnableModule for X64ExecutionContext {
|
|||||||
let args =
|
let args =
|
||||||
slice::from_raw_parts(args, num_params_plus_one.unwrap().as_ptr() as usize - 1);
|
slice::from_raw_parts(args, num_params_plus_one.unwrap().as_ptr() as usize - 1);
|
||||||
|
|
||||||
let ret = match protect_unix::call_protected(
|
let ret = match fault::catch_unsafe_unwind(
|
||||||
|| {
|
|| {
|
||||||
|
// Puts the arguments onto the stack and calls Wasm entry.
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
{
|
{
|
||||||
let args_reverse: SmallVec<[u64; 8]> = args.iter().cloned().rev().collect();
|
let args_reverse: SmallVec<[u64; 8]> = args.iter().cloned().rev().collect();
|
||||||
@ -395,6 +400,9 @@ impl RunnableModule for X64ExecutionContext {
|
|||||||
func.as_ptr(),
|
func.as_ptr(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME: Currently we are doing a hack here to convert between native aarch64 and
|
||||||
|
// "emulated" x86 ABIs. Ideally, this should be done using handwritten assembly.
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
{
|
{
|
||||||
struct CallCtx<'a> {
|
struct CallCtx<'a> {
|
||||||
@ -519,7 +527,7 @@ impl RunnableModule for X64ExecutionContext {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
*error_out = Some(err.0);
|
*error_out = Some(err);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -545,8 +553,7 @@ impl RunnableModule for X64ExecutionContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn do_early_trap(&self, data: Box<dyn Any + Send>) -> ! {
|
unsafe fn do_early_trap(&self, data: Box<dyn Any + Send>) -> ! {
|
||||||
protect_unix::TRAP_EARLY_DATA.with(|x| x.set(Some(data)));
|
fault::begin_unsafe_unwind(data);
|
||||||
protect_unix::trigger_trap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_code(&self) -> Option<&[u8]> {
|
fn get_code(&self) -> Option<&[u8]> {
|
||||||
@ -1686,14 +1693,11 @@ impl X64FunctionCode {
|
|||||||
Location::GPR(GPR::RSP),
|
Location::GPR(GPR::RSP),
|
||||||
);
|
);
|
||||||
|
|
||||||
// FIXME: Possible dynasm bug. This is a workaround.
|
|
||||||
// Using RSP as the source/destination operand of a `mov` instruction produces invalid code.
|
|
||||||
a.emit_mov(Size::S64, Location::GPR(GPR::RSP), Location::GPR(GPR::RCX));
|
|
||||||
for (i, r) in used_xmms.iter().enumerate() {
|
for (i, r) in used_xmms.iter().enumerate() {
|
||||||
a.emit_mov(
|
a.emit_mov(
|
||||||
Size::S64,
|
Size::S64,
|
||||||
Location::XMM(*r),
|
Location::XMM(*r),
|
||||||
Location::Memory(GPR::RCX, (i * 8) as i32),
|
Location::Memory(GPR::RSP, (i * 8) as i32),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for r in used_xmms.iter().rev() {
|
for r in used_xmms.iter().rev() {
|
||||||
@ -1771,37 +1775,26 @@ impl X64FunctionCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
match *param {
|
match *param {
|
||||||
// Dynasm bug: RSP in memory operand does not work
|
Location::Imm64(_) => {
|
||||||
Location::Imm64(_) | Location::XMM(_) => {
|
// Dummy value slot to be filled with `mov`.
|
||||||
|
a.emit_push(Size::S64, Location::GPR(GPR::RAX));
|
||||||
|
|
||||||
|
// Use R10 as the temporary register here, since it is callee-saved and not
|
||||||
|
// used by the callback `cb`.
|
||||||
|
a.emit_mov(Size::S64, *param, Location::GPR(GPR::R10));
|
||||||
a.emit_mov(
|
a.emit_mov(
|
||||||
Size::S64,
|
Size::S64,
|
||||||
Location::GPR(GPR::RAX),
|
Location::GPR(GPR::R10),
|
||||||
Location::XMM(XMM::XMM0),
|
Location::Memory(GPR::RSP, 0),
|
||||||
);
|
|
||||||
a.emit_mov(
|
|
||||||
Size::S64,
|
|
||||||
Location::GPR(GPR::RCX),
|
|
||||||
Location::XMM(XMM::XMM1),
|
|
||||||
);
|
|
||||||
a.emit_sub(Size::S64, Location::Imm32(8), Location::GPR(GPR::RSP));
|
|
||||||
a.emit_mov(Size::S64, Location::GPR(GPR::RSP), Location::GPR(GPR::RCX));
|
|
||||||
a.emit_mov(Size::S64, *param, Location::GPR(GPR::RAX));
|
|
||||||
a.emit_mov(
|
|
||||||
Size::S64,
|
|
||||||
Location::GPR(GPR::RAX),
|
|
||||||
Location::Memory(GPR::RCX, 0),
|
|
||||||
);
|
|
||||||
a.emit_mov(
|
|
||||||
Size::S64,
|
|
||||||
Location::XMM(XMM::XMM0),
|
|
||||||
Location::GPR(GPR::RAX),
|
|
||||||
);
|
|
||||||
a.emit_mov(
|
|
||||||
Size::S64,
|
|
||||||
Location::XMM(XMM::XMM1),
|
|
||||||
Location::GPR(GPR::RCX),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Location::XMM(_) => {
|
||||||
|
// Dummy value slot to be filled with `mov`.
|
||||||
|
a.emit_push(Size::S64, Location::GPR(GPR::RAX));
|
||||||
|
|
||||||
|
// XMM registers can be directly stored to memory.
|
||||||
|
a.emit_mov(Size::S64, *param, Location::Memory(GPR::RSP, 0));
|
||||||
|
}
|
||||||
_ => a.emit_push(Size::S64, *param),
|
_ => a.emit_push(Size::S64, *param),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1873,12 +1866,10 @@ impl X64FunctionCode {
|
|||||||
|
|
||||||
// Restore XMMs.
|
// Restore XMMs.
|
||||||
if used_xmms.len() > 0 {
|
if used_xmms.len() > 0 {
|
||||||
// FIXME: Possible dynasm bug. This is a workaround.
|
|
||||||
a.emit_mov(Size::S64, Location::GPR(GPR::RSP), Location::GPR(GPR::RDX));
|
|
||||||
for (i, r) in used_xmms.iter().enumerate() {
|
for (i, r) in used_xmms.iter().enumerate() {
|
||||||
a.emit_mov(
|
a.emit_mov(
|
||||||
Size::S64,
|
Size::S64,
|
||||||
Location::Memory(GPR::RDX, (i * 8) as i32),
|
Location::Memory(GPR::RSP, (i * 8) as i32),
|
||||||
Location::XMM(*r),
|
Location::XMM(*r),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,6 @@ extern crate smallvec;
|
|||||||
mod codegen_x64;
|
mod codegen_x64;
|
||||||
mod emitter_x64;
|
mod emitter_x64;
|
||||||
mod machine;
|
mod machine;
|
||||||
pub mod protect_unix;
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
mod translator_aarch64;
|
mod translator_aarch64;
|
||||||
|
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
//! Installing signal handlers allows us to handle traps and out-of-bounds memory
|
|
||||||
//! accesses that occur when runniing WebAssembly.
|
|
||||||
//!
|
|
||||||
//! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622
|
|
||||||
//!
|
|
||||||
//! When a WebAssembly module triggers any traps, we perform recovery here.
|
|
||||||
//!
|
|
||||||
//! This module uses TLS (thread-local storage) to track recovery information. Since the four signals we're handling
|
|
||||||
//! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here
|
|
||||||
//! unless you have memory unsafety elsewhere in your code.
|
|
||||||
//!
|
|
||||||
use std::any::Any;
|
|
||||||
use std::cell::Cell;
|
|
||||||
use wasmer_runtime_core::codegen::BreakpointMap;
|
|
||||||
use wasmer_runtime_core::fault::{begin_unsafe_unwind, catch_unsafe_unwind, ensure_sighandler};
|
|
||||||
|
|
||||||
thread_local! {
|
|
||||||
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any + Send>>> = Cell::new(None);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn trigger_trap() -> ! {
|
|
||||||
begin_unsafe_unwind(Box::new(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CallProtError(pub Box<dyn Any + Send>);
|
|
||||||
|
|
||||||
pub fn call_protected<T>(
|
|
||||||
f: impl FnOnce() -> T,
|
|
||||||
breakpoints: Option<BreakpointMap>,
|
|
||||||
) -> Result<T, CallProtError> {
|
|
||||||
ensure_sighandler();
|
|
||||||
unsafe {
|
|
||||||
let ret = catch_unsafe_unwind(|| f(), breakpoints);
|
|
||||||
match ret {
|
|
||||||
Ok(x) => Ok(x),
|
|
||||||
Err(e) => Err(CallProtError(
|
|
||||||
if let Some(data) = TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
|
||||||
data
|
|
||||||
} else {
|
|
||||||
e
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn throw(payload: Box<dyn Any + Send>) -> ! {
|
|
||||||
begin_unsafe_unwind(payload);
|
|
||||||
}
|
|
Reference in New Issue
Block a user