forked from wasmerio/wasmer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split Artifact to have ArtifactCreate that handles only the creation …
…part, not the run part
- Loading branch information
Showing
28 changed files
with
728 additions
and
569 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "wasmer-artifact" | ||
version = "2.2.1" | ||
description = "Wasmer Artifact abstraction" | ||
categories = ["wasm"] | ||
keywords = ["wasm", "webassembly", "engine"] | ||
authors = ["Wasmer Engineering Team <[email protected]>"] | ||
repository = "https://github.com/wasmerio/wasmer" | ||
license = "MIT OR Apache-2.0 WITH LLVM-exception " | ||
readme = "README.md" | ||
edition = "2018" | ||
|
||
[dependencies] | ||
wasmer-types = { path = "../types", version = "=2.2.1" } | ||
wasmer-compiler = { path = "../compiler", version = "=2.2.1" } | ||
loupe = "0.1" | ||
thiserror = "1.0" | ||
enumset = "1.0" | ||
|
||
[badges] | ||
maintenance = { status = "actively-developed" } | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# `wasmer-artifact` [![Build Status](https://github.com/wasmerio/wasmer/workflows/build/badge.svg?style=flat-square)](https://github.com/wasmerio/wasmer/actions?query=workflow%3Abuild) [![Join Wasmer Slack](https://img.shields.io/static/v1?label=Slack&message=join%20chat&color=brighgreen&style=flat-square)](https://slack.wasmer.io) [![MIT License](https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square)](https://github.com/wasmerio/wasmer/blob/master/LICENSE) | ||
|
||
|
||
This crate is the general abstraction for creating Artifacts in Wasmer. | ||
|
||
### Acknowledgments | ||
|
||
This project borrowed some of the code of the trap implementation from | ||
the [`wasmtime-api`], the code since then has evolved significantly. | ||
|
||
Please check [Wasmer `ATTRIBUTIONS`] to further see licenses and other | ||
attributions of the project. | ||
|
||
|
||
[`wasmer-engine-universal`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-universal | ||
[`wasmer-engine-dylib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-dylib | ||
[`wasmer-engine-staticlib`]: https://github.com/wasmerio/wasmer/tree/master/lib/engine-staticlib | ||
[`wasmer-engine-dummy`]: https://github.com/wasmerio/wasmer/tree/master/tests/lib/engine-dummy | ||
[`wasmtime-api`]: https://crates.io/crates/wasmtime | ||
[Wasmer `ATTRIBUTIONS`]: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
use crate::{DeserializeError, SerializeError}; | ||
use enumset::EnumSet; | ||
use loupe::MemoryUsage; | ||
use std::any::Any; | ||
use std::convert::TryInto; | ||
use std::path::Path; | ||
use std::sync::Arc; | ||
use std::{fs, mem}; | ||
use wasmer_compiler::{CpuFeature, Features}; | ||
use wasmer_types::entity::PrimaryMap; | ||
use wasmer_types::{ | ||
MemoryIndex, MemoryStyle, ModuleInfo, OwnedDataInitializer, TableIndex, TableStyle, | ||
}; | ||
|
||
/// An `Artifact` is the product that the `Engine` | ||
/// implementation produce and use. | ||
/// | ||
/// The `Artifact` contains the compiled data for a given | ||
/// module as well as extra information needed to run the | ||
/// module at runtime, such as [`ModuleInfo`] and [`Features`]. | ||
pub trait ArtifactCreate: Send + Sync + Upcastable + MemoryUsage { | ||
/// Return a reference-counted pointer to the module | ||
fn module(&self) -> Arc<ModuleInfo>; | ||
|
||
/// Return a pointer to a module. | ||
fn module_ref(&self) -> &ModuleInfo; | ||
|
||
/// Gets a mutable reference to the info. | ||
/// | ||
/// Note: this will return `None` if the module is already instantiated. | ||
fn module_mut(&mut self) -> Option<&mut ModuleInfo>; | ||
|
||
/// Register thie `Artifact` stack frame information into the global scope. | ||
/// | ||
/// This is required to ensure that any traps can be properly symbolicated. | ||
fn register_frame_info(&self); | ||
|
||
/// Returns the features for this Artifact | ||
fn features(&self) -> &Features; | ||
|
||
/// Returns the CPU features for this Artifact | ||
fn cpu_features(&self) -> EnumSet<CpuFeature>; | ||
|
||
/// Returns the memory styles associated with this `Artifact`. | ||
fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle>; | ||
|
||
/// Returns the table plans associated with this `Artifact`. | ||
fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle>; | ||
|
||
/// Returns data initializers to pass to `InstanceHandle::initialize` | ||
fn data_initializers(&self) -> &[OwnedDataInitializer]; | ||
|
||
/// Serializes an artifact into bytes | ||
fn serialize(&self) -> Result<Vec<u8>, SerializeError>; | ||
|
||
/// Serializes an artifact into a file path | ||
fn serialize_to_file(&self, path: &Path) -> Result<(), SerializeError> { | ||
let serialized = self.serialize()?; | ||
fs::write(&path, serialized)?; | ||
Ok(()) | ||
} | ||
} | ||
|
||
// Implementation of `Upcastable` taken from https://users.rust-lang.org/t/why-does-downcasting-not-work-for-subtraits/33286/7 . | ||
/// Trait needed to get downcasting of `Engine`s to work. | ||
pub trait Upcastable { | ||
/// upcast ref | ||
fn upcast_any_ref(&'_ self) -> &'_ dyn Any; | ||
/// upcast mut ref | ||
fn upcast_any_mut(&'_ mut self) -> &'_ mut dyn Any; | ||
/// upcast boxed dyn | ||
fn upcast_any_box(self: Box<Self>) -> Box<dyn Any>; | ||
} | ||
|
||
impl<T: Any + Send + Sync + 'static> Upcastable for T { | ||
#[inline] | ||
fn upcast_any_ref(&'_ self) -> &'_ dyn Any { | ||
self | ||
} | ||
#[inline] | ||
fn upcast_any_mut(&'_ mut self) -> &'_ mut dyn Any { | ||
self | ||
} | ||
#[inline] | ||
fn upcast_any_box(self: Box<Self>) -> Box<dyn Any> { | ||
self | ||
} | ||
} | ||
|
||
impl dyn ArtifactCreate + 'static { | ||
/// Try to downcast the artifact into a given type. | ||
#[inline] | ||
pub fn downcast_ref<T: 'static>(&'_ self) -> Option<&'_ T> { | ||
self.upcast_any_ref().downcast_ref::<T>() | ||
} | ||
|
||
/// Try to downcast the artifact into a given type mutably. | ||
#[inline] | ||
pub fn downcast_mut<T: 'static>(&'_ mut self) -> Option<&'_ mut T> { | ||
self.upcast_any_mut().downcast_mut::<T>() | ||
} | ||
} | ||
|
||
/// Metadata header which holds an ABI version and the length of the remaining | ||
/// metadata. | ||
#[repr(C)] | ||
#[derive(Clone, Copy)] | ||
pub struct MetadataHeader { | ||
magic: [u8; 8], | ||
version: u32, | ||
len: u32, | ||
} | ||
|
||
impl MetadataHeader { | ||
/// Current ABI version. Increment this any time breaking changes are made | ||
/// to the format of the serialized data. | ||
const CURRENT_VERSION: u32 = 1; | ||
|
||
/// Magic number to identify wasmer metadata. | ||
const MAGIC: [u8; 8] = *b"WASMER\0\0"; | ||
|
||
/// Length of the metadata header. | ||
pub const LEN: usize = 16; | ||
|
||
/// Alignment of the metadata. | ||
pub const ALIGN: usize = 16; | ||
|
||
/// Creates a new header for metadata of the given length. | ||
pub fn new(len: usize) -> [u8; 16] { | ||
let header = MetadataHeader { | ||
magic: Self::MAGIC, | ||
version: Self::CURRENT_VERSION, | ||
len: len.try_into().expect("metadata exceeds maximum length"), | ||
}; | ||
unsafe { mem::transmute(header) } | ||
} | ||
|
||
/// Parses the header and returns the length of the metadata following it. | ||
pub fn parse(bytes: &[u8]) -> Result<usize, DeserializeError> { | ||
if bytes.as_ptr() as usize % 16 != 0 { | ||
return Err(DeserializeError::CorruptedBinary( | ||
"misaligned metadata".to_string(), | ||
)); | ||
} | ||
let bytes: [u8; 16] = bytes | ||
.get(..16) | ||
.ok_or_else(|| { | ||
DeserializeError::CorruptedBinary("invalid metadata header".to_string()) | ||
})? | ||
.try_into() | ||
.unwrap(); | ||
let header: MetadataHeader = unsafe { mem::transmute(bytes) }; | ||
if header.magic != Self::MAGIC { | ||
return Err(DeserializeError::Incompatible( | ||
"The provided bytes were not serialized by Wasmer".to_string(), | ||
)); | ||
} | ||
if header.version != Self::CURRENT_VERSION { | ||
return Err(DeserializeError::Incompatible( | ||
"The provided bytes were serialized by an incompatible version of Wasmer" | ||
.to_string(), | ||
)); | ||
} | ||
Ok(header.len as usize) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
//! The WebAssembly possible errors | ||
use std::io; | ||
use thiserror::Error; | ||
use wasmer_compiler::CompileError; | ||
use wasmer_types::ExternType; | ||
|
||
/// The Serialize error can occur when serializing a | ||
/// compiled Module into a binary. | ||
#[derive(Error, Debug)] | ||
pub enum SerializeError { | ||
/// An IO error | ||
#[error(transparent)] | ||
Io(#[from] io::Error), | ||
/// A generic serialization error | ||
#[error("{0}")] | ||
Generic(String), | ||
} | ||
|
||
/// The Deserialize error can occur when loading a | ||
/// compiled Module from a binary. | ||
#[derive(Error, Debug)] | ||
pub enum DeserializeError { | ||
/// An IO error | ||
#[error(transparent)] | ||
Io(#[from] io::Error), | ||
/// A generic deserialization error | ||
#[error("{0}")] | ||
Generic(String), | ||
/// Incompatible serialized binary | ||
#[error("incompatible binary: {0}")] | ||
Incompatible(String), | ||
/// The provided binary is corrupted | ||
#[error("corrupted binary: {0}")] | ||
CorruptedBinary(String), | ||
/// The binary was valid, but we got an error when | ||
/// trying to allocate the required resources. | ||
#[error(transparent)] | ||
Compiler(CompileError), | ||
} | ||
|
||
/// An ImportError. | ||
/// | ||
/// Note: this error is not standard to WebAssembly, but it's | ||
/// useful to determine the import issue on the API side. | ||
#[derive(Error, Debug)] | ||
pub enum ImportError { | ||
/// Incompatible Import Type. | ||
/// This error occurs when the import types mismatch. | ||
#[error("incompatible import type. Expected {0:?} but received {1:?}")] | ||
IncompatibleType(ExternType, ExternType), | ||
|
||
/// Unknown Import. | ||
/// This error occurs when an import was expected but not provided. | ||
#[error("unknown import. Expected {0:?}")] | ||
UnknownImport(ExternType), | ||
} | ||
|
||
/// An error while preinstantiating a module. | ||
/// | ||
#[derive(Error, Debug)] | ||
pub enum PreInstantiationError { | ||
/// The module was compiled with a CPU feature that is not available on | ||
/// the current host. | ||
#[error("module compiled with CPU feature that is missing from host")] | ||
CpuFeature(String), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/// A placeholder byte-sized type which is just used to provide some amount of type | ||
/// safety when dealing with pointers to JIT-compiled function bodies. Note that it's | ||
/// deliberately not Copy, as we shouldn't be carelessly copying function body bytes | ||
/// around. | ||
#[repr(C)] | ||
pub struct VMFunctionBody(u8); | ||
|
||
#[cfg(test)] | ||
mod test_vmfunction_body { | ||
use super::VMFunctionBody; | ||
use std::mem::size_of; | ||
|
||
#[test] | ||
fn check_vmfunction_body_offsets() { | ||
assert_eq!(size_of::<VMFunctionBody>(), 1); | ||
} | ||
} |
Oops, something went wrong.