Split Artifact to have ArtifactCreate that handles only the creation part, not the run part

This commit is contained in:
ptitSeb
2022-03-25 20:00:29 +01:00
parent 1783aa50f1
commit 1f3613c881
28 changed files with 728 additions and 569 deletions

19
Cargo.lock generated
View File

@@ -2765,6 +2765,7 @@ dependencies = [
"thiserror", "thiserror",
"wasm-bindgen", "wasm-bindgen",
"wasm-bindgen-test", "wasm-bindgen-test",
"wasmer-artifact",
"wasmer-compiler", "wasmer-compiler",
"wasmer-compiler-cranelift", "wasmer-compiler-cranelift",
"wasmer-compiler-llvm", "wasmer-compiler-llvm",
@@ -2780,6 +2781,17 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "wasmer-artifact"
version = "2.2.1"
dependencies = [
"enumset",
"loupe",
"thiserror",
"wasmer-compiler",
"wasmer-types",
]
[[package]] [[package]]
name = "wasmer-bin-fuzz" name = "wasmer-bin-fuzz"
version = "0.0.0" version = "0.0.0"
@@ -2858,6 +2870,7 @@ dependencies = [
"tempfile", "tempfile",
"unix_mode", "unix_mode",
"wasmer", "wasmer",
"wasmer-artifact",
"wasmer-cache", "wasmer-cache",
"wasmer-compiler", "wasmer-compiler",
"wasmer-compiler-cranelift", "wasmer-compiler-cranelift",
@@ -2996,6 +3009,7 @@ dependencies = [
"serde_bytes", "serde_bytes",
"target-lexicon 0.12.3", "target-lexicon 0.12.3",
"thiserror", "thiserror",
"wasmer-artifact",
"wasmer-compiler", "wasmer-compiler",
"wasmer-types", "wasmer-types",
"wasmer-vm", "wasmer-vm",
@@ -3010,6 +3024,7 @@ dependencies = [
"loupe", "loupe",
"serde", "serde",
"serde_bytes", "serde_bytes",
"wasmer-artifact",
"wasmer-compiler", "wasmer-compiler",
"wasmer-engine", "wasmer-engine",
"wasmer-types", "wasmer-types",
@@ -3031,6 +3046,7 @@ dependencies = [
"serde", "serde",
"tempfile", "tempfile",
"tracing", "tracing",
"wasmer-artifact",
"wasmer-compiler", "wasmer-compiler",
"wasmer-engine", "wasmer-engine",
"wasmer-object", "wasmer-object",
@@ -3052,6 +3068,7 @@ dependencies = [
"serde", "serde",
"tempfile", "tempfile",
"tracing", "tracing",
"wasmer-artifact",
"wasmer-compiler", "wasmer-compiler",
"wasmer-engine", "wasmer-engine",
"wasmer-object", "wasmer-object",
@@ -3070,6 +3087,7 @@ dependencies = [
"loupe", "loupe",
"region", "region",
"rkyv", "rkyv",
"wasmer-artifact",
"wasmer-compiler", "wasmer-compiler",
"wasmer-engine", "wasmer-engine",
"wasmer-types", "wasmer-types",
@@ -3156,6 +3174,7 @@ dependencies = [
"scopeguard", "scopeguard",
"serde", "serde",
"thiserror", "thiserror",
"wasmer-artifact",
"wasmer-types", "wasmer-types",
"winapi", "winapi",
] ]

View File

@@ -22,6 +22,7 @@ edition = "2018"
# Shared dependencies. # Shared dependencies.
[dependencies] [dependencies]
# - Mandatory shared dependencies. # - Mandatory shared dependencies.
wasmer-artifact = { path = "../artifact", version = "=2.2.1" }
indexmap = { version = "1.6", features = ["serde-1"] } indexmap = { version = "1.6", features = ["serde-1"] }
cfg-if = "1.0" cfg-if = "1.0"
thiserror = "1.0" thiserror = "1.0"

22
lib/artifact/Cargo.toml Normal file
View File

@@ -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 <engineering@wasmer.io>"]
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" }

20
lib/artifact/README.md Normal file
View File

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

View File

@@ -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)
}
}

66
lib/artifact/src/error.rs Normal file
View File

@@ -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),
}

View File

@@ -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);
}
}

55
lib/artifact/src/lib.rs Normal file
View File

@@ -0,0 +1,55 @@
//! Generic Artifact abstraction for Wasmer Engines.
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces)]
#![cfg_attr(
feature = "cargo-clippy",
allow(clippy::new_without_default, clippy::new_without_default)
)]
#![cfg_attr(
feature = "cargo-clippy",
warn(
clippy::float_arithmetic,
clippy::mut_mut,
clippy::nonminimal_bool,
clippy::option_map_unwrap_or,
clippy::option_map_unwrap_or_else,
clippy::print_stdout,
clippy::unicode_not_nfc,
clippy::use_self
)
)]
mod artifact;
mod error;
mod funcbody;
pub use crate::artifact::{ArtifactCreate, MetadataHeader, Upcastable};
pub use crate::error::{DeserializeError, ImportError, PreInstantiationError, SerializeError};
pub use crate::funcbody::VMFunctionBody;
use loupe::MemoryUsage;
/// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
/// A safe wrapper around `VMFunctionBody`.
#[derive(Clone, Copy, Debug, MemoryUsage)]
#[repr(transparent)]
pub struct FunctionBodyPtr(pub *const VMFunctionBody);
impl std::ops::Deref for FunctionBodyPtr {
type Target = *const VMFunctionBody;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// # Safety
/// The VMFunctionBody that this points to is opaque, so there's no data to
/// read or write through this pointer. This is essentially a usize.
unsafe impl Send for FunctionBodyPtr {}
/// # Safety
/// The VMFunctionBody that this points to is opaque, so there's no data to
/// read or write through this pointer. This is essentially a usize.
unsafe impl Sync for FunctionBodyPtr {}

View File

@@ -24,6 +24,7 @@ doc = false
required-features = ["headless"] required-features = ["headless"]
[dependencies] [dependencies]
wasmer-artifact = { version = "=2.2.1", path = "../artifact" }
wasmer-compiler = { version = "=2.2.1", path = "../compiler" } wasmer-compiler = { version = "=2.2.1", path = "../compiler" }
wasmer-compiler-singlepass = { version = "=2.2.1", path = "../compiler-singlepass", optional = true } wasmer-compiler-singlepass = { version = "=2.2.1", path = "../compiler-singlepass", optional = true }
wasmer-engine = { version = "=2.2.1", path = "../engine" } wasmer-engine = { version = "=2.2.1", path = "../engine" }

View File

@@ -11,6 +11,7 @@ readme = "README.md"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wasmer-artifact = { path = "../artifact", version = "=2.2.1" }
wasmer-types = { path = "../types", version = "=2.2.1" } wasmer-types = { path = "../types", version = "=2.2.1" }
wasmer-compiler = { path = "../compiler", version = "=2.2.1" } wasmer-compiler = { path = "../compiler", version = "=2.2.1" }
wasmer-vm = { path = "../vm", version = "=2.2.1", features = ["enable-rkyv"] } wasmer-vm = { path = "../vm", version = "=2.2.1", features = ["enable-rkyv"] }

View File

@@ -19,6 +19,7 @@ use tempfile::NamedTempFile;
use tracing::log::error; use tracing::log::error;
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
use tracing::trace; use tracing::trace;
use wasmer_artifact::ArtifactCreate;
use wasmer_compiler::{ use wasmer_compiler::{
Architecture, CompileError, CompiledFunctionFrameInfo, CpuFeature, Features, Architecture, CompileError, CompiledFunctionFrameInfo, CpuFeature, Features,
FunctionAddressMap, OperatingSystem, Symbol, SymbolRegistry, Triple, FunctionAddressMap, OperatingSystem, Symbol, SymbolRegistry, Triple,
@@ -678,7 +679,7 @@ impl DylibArtifact {
} }
} }
impl Artifact for DylibArtifact { impl ArtifactCreate for DylibArtifact {
fn module(&self) -> Arc<ModuleInfo> { fn module(&self) -> Arc<ModuleInfo> {
self.metadata.compile_info.module.clone() self.metadata.compile_info.module.clone()
} }
@@ -841,30 +842,6 @@ impl Artifact for DylibArtifact {
&self.metadata.compile_info.table_styles &self.metadata.compile_info.table_styles
} }
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
&self.finished_functions
}
fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
&self.finished_function_call_trampolines
}
fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
&self.finished_dynamic_function_trampolines
}
fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
&self.signatures
}
fn func_data_registry(&self) -> &FuncDataRegistry {
&self.func_data_registry
}
fn preinstantiate(&self) -> Result<(), InstantiationError> {
Ok(())
}
/// Serialize a `DylibArtifact`. /// Serialize a `DylibArtifact`.
fn serialize(&self) -> Result<Vec<u8>, SerializeError> { fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
Ok(std::fs::read(&self.dylib_path)?) Ok(std::fs::read(&self.dylib_path)?)
@@ -908,3 +885,28 @@ impl Artifact for DylibArtifact {
Ok(()) Ok(())
} }
} }
impl Artifact for DylibArtifact {
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
&self.finished_functions
}
fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
&self.finished_function_call_trampolines
}
fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
&self.finished_dynamic_function_trampolines
}
fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
&self.signatures
}
fn func_data_registry(&self) -> &FuncDataRegistry {
&self.func_data_registry
}
fn preinstantiate(&self) -> Result<(), InstantiationError> {
Ok(())
}
}

View File

@@ -11,6 +11,7 @@ readme = "README.md"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wasmer-artifact = { path = "../artifact", version = "=2.2.1" }
wasmer-types = { path = "../types", version = "=2.2.1" } wasmer-types = { path = "../types", version = "=2.2.1" }
wasmer-compiler = { path = "../compiler", version = "=2.2.1" } wasmer-compiler = { path = "../compiler", version = "=2.2.1" }
wasmer-vm = { path = "../vm", version = "=2.2.1" } wasmer-vm = { path = "../vm", version = "=2.2.1" }

View File

@@ -9,6 +9,7 @@ use std::collections::BTreeMap;
use std::error::Error; use std::error::Error;
use std::mem; use std::mem;
use std::sync::Arc; use std::sync::Arc;
use wasmer_artifact::ArtifactCreate;
use wasmer_compiler::{ use wasmer_compiler::{
CompileError, CpuFeature, Features, OperatingSystem, SymbolRegistry, Triple, CompileError, CpuFeature, Features, OperatingSystem, SymbolRegistry, Triple,
}; };
@@ -436,7 +437,7 @@ impl StaticlibArtifact {
} }
} }
impl Artifact for StaticlibArtifact { impl ArtifactCreate for StaticlibArtifact {
fn module(&self) -> Arc<ModuleInfo> { fn module(&self) -> Arc<ModuleInfo> {
self.metadata.compile_info.module.clone() self.metadata.compile_info.module.clone()
} }
@@ -473,6 +474,12 @@ impl Artifact for StaticlibArtifact {
&self.metadata.compile_info.table_styles &self.metadata.compile_info.table_styles
} }
/// Serialize a StaticlibArtifact
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
Ok(self.module_bytes.clone())
}
}
impl Artifact for StaticlibArtifact {
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> { fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
&self.finished_functions &self.finished_functions
} }
@@ -492,7 +499,6 @@ impl Artifact for StaticlibArtifact {
fn func_data_registry(&self) -> &FuncDataRegistry { fn func_data_registry(&self) -> &FuncDataRegistry {
&self.func_data_registry &self.func_data_registry
} }
fn preinstantiate(&self) -> Result<(), InstantiationError> { fn preinstantiate(&self) -> Result<(), InstantiationError> {
if self.is_compiled { if self.is_compiled {
panic!( panic!(
@@ -502,9 +508,4 @@ impl Artifact for StaticlibArtifact {
} }
Ok(()) Ok(())
} }
/// Serialize a StaticlibArtifact
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
Ok(self.module_bytes.clone())
}
} }

View File

@@ -11,6 +11,7 @@ readme = "README.md"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
wasmer-artifact = { path = "../artifact", version = "=2.2.1" }
wasmer-types = { path = "../types", version = "=2.2.1", features = [ wasmer-types = { path = "../types", version = "=2.2.1", features = [
"enable-rkyv", "enable-rkyv",
] } ] }
@@ -21,7 +22,6 @@ wasmer-compiler = { path = "../compiler", version = "=2.2.1", features = [
wasmer-vm = { path = "../vm", version = "=2.2.1", features = ["enable-rkyv"] } wasmer-vm = { path = "../vm", version = "=2.2.1", features = ["enable-rkyv"] }
wasmer-engine = { path = "../engine", version = "=2.2.1" } wasmer-engine = { path = "../engine", version = "=2.2.1" }
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
region = { version = "3.0" }
cfg-if = "1.0" cfg-if = "1.0"
leb128 = "0.2" leb128 = "0.2"
rkyv = "0.7.20" rkyv = "0.7.20"
@@ -29,6 +29,9 @@ loupe = "0.1"
enumset = "1.0" enumset = "1.0"
enum-iterator = "0.7.0" enum-iterator = "0.7.0"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
region = { version = "3.0" }
[target.'cfg(target_os = "windows")'.dependencies] [target.'cfg(target_os = "windows")'.dependencies]
winapi = { version = "0.3", features = ["winnt", "impl-default"] } winapi = { version = "0.3", features = ["winnt", "impl-default"] }

View File

@@ -11,6 +11,7 @@ use enumset::EnumSet;
use loupe::MemoryUsage; use loupe::MemoryUsage;
use std::mem; use std::mem;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use wasmer_artifact::ArtifactCreate;
use wasmer_compiler::{CompileError, CpuFeature, Features, Triple}; use wasmer_compiler::{CompileError, CpuFeature, Features, Triple};
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment, ModuleMiddlewareChain}; use wasmer_compiler::{CompileModuleInfo, ModuleEnvironment, ModuleMiddlewareChain};
@@ -267,7 +268,7 @@ impl UniversalArtifact {
} }
} }
impl Artifact for UniversalArtifact { impl ArtifactCreate for UniversalArtifact {
fn module(&self) -> Arc<ModuleInfo> { fn module(&self) -> Arc<ModuleInfo> {
self.serializable.compile_info.module.clone() self.serializable.compile_info.module.clone()
} }
@@ -324,6 +325,19 @@ impl Artifact for UniversalArtifact {
&self.serializable.compile_info.table_styles &self.serializable.compile_info.table_styles
} }
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
let serialized_data = self.serializable.serialize()?;
assert!(mem::align_of::<SerializableModule>() <= MetadataHeader::ALIGN);
let mut metadata_binary = vec![];
metadata_binary.extend(Self::MAGIC_HEADER);
metadata_binary.extend(MetadataHeader::new(serialized_data.len()));
metadata_binary.extend(serialized_data);
Ok(metadata_binary)
}
}
impl Artifact for UniversalArtifact {
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> { fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
&self.finished_functions &self.finished_functions
} }
@@ -343,14 +357,4 @@ impl Artifact for UniversalArtifact {
fn func_data_registry(&self) -> &FuncDataRegistry { fn func_data_registry(&self) -> &FuncDataRegistry {
&self.func_data_registry &self.func_data_registry
} }
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
let serialized_data = self.serializable.serialize()?;
assert!(mem::align_of::<SerializableModule>() <= MetadataHeader::ALIGN);
let mut metadata_binary = vec![];
metadata_binary.extend(Self::MAGIC_HEADER);
metadata_binary.extend(MetadataHeader::new(serialized_data.len()));
metadata_binary.extend(serialized_data);
Ok(metadata_binary)
}
} }

View File

@@ -13,6 +13,7 @@ edition = "2018"
[dependencies] [dependencies]
wasmer-types = { path = "../types", version = "=2.2.1" } wasmer-types = { path = "../types", version = "=2.2.1" }
wasmer-compiler = { path = "../compiler", version = "=2.2.1" } wasmer-compiler = { path = "../compiler", version = "=2.2.1" }
wasmer-artifact = { path = "../artifact", version = "=2.2.1" }
target-lexicon = { version = "0.12.2", default-features = false } target-lexicon = { version = "0.12.2", default-features = false }
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
backtrace = "0.3" backtrace = "0.3"

View File

@@ -1,63 +1,26 @@
use crate::{ use crate::{resolve_imports, InstantiationError, Resolver, RuntimeError, Tunables};
resolve_imports, DeserializeError, InstantiationError, Resolver, RuntimeError, SerializeError,
Tunables,
};
use enumset::EnumSet;
use loupe::MemoryUsage; use loupe::MemoryUsage;
use std::any::Any; use std::any::Any;
use std::convert::TryInto; pub use wasmer_artifact::MetadataHeader;
use std::path::Path; use wasmer_artifact::{ArtifactCreate, Upcastable};
use std::sync::Arc; use wasmer_compiler::CpuFeature;
use std::{fs, mem}; use wasmer_types::entity::BoxedSlice;
use wasmer_compiler::{CpuFeature, Features}; use wasmer_types::{DataInitializer, FunctionIndex, LocalFunctionIndex, SignatureIndex};
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
use wasmer_types::{
DataInitializer, FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo,
OwnedDataInitializer, SignatureIndex, TableIndex,
};
use wasmer_vm::{ use wasmer_vm::{
FuncDataRegistry, FunctionBodyPtr, InstanceAllocator, InstanceHandle, MemoryStyle, TableStyle, FuncDataRegistry, FunctionBodyPtr, InstanceAllocator, InstanceHandle, TrapHandler,
TrapHandler, VMSharedSignatureIndex, VMTrampoline, VMSharedSignatureIndex, VMTrampoline,
}; };
/// An `Artifact` is the product that the `Engine` /// An `Artifact` is the product that the `Engine`
/// implementation produce and use. /// implementation produce and use.
/// ///
/// The `Artifact` contains the compiled data for a given
/// module as well as extra information needed to run the /// An `Artifact` is the product that the `Engine`
/// implementation produce and use.
///
/// The `ArtifactRun` contains the extra information needed to run the
/// module at runtime, such as [`ModuleInfo`] and [`Features`]. /// module at runtime, such as [`ModuleInfo`] and [`Features`].
pub trait Artifact: Send + Sync + Upcastable + MemoryUsage { pub trait Artifact: Send + Sync + Upcastable + MemoryUsage + ArtifactCreate {
/// 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];
/// Returns the functions allocated in memory or this `Artifact` /// Returns the functions allocated in memory or this `Artifact`
/// ready to be run. /// ready to be run.
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>; fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>;
@@ -76,21 +39,10 @@ pub trait Artifact: Send + Sync + Upcastable + MemoryUsage {
/// Get the func data registry /// Get the func data registry
fn func_data_registry(&self) -> &FuncDataRegistry; fn func_data_registry(&self) -> &FuncDataRegistry;
/// 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(())
}
/// Do preinstantiation logic that is executed before instantiating /// Do preinstantiation logic that is executed before instantiating
fn preinstantiate(&self) -> Result<(), InstantiationError> { fn preinstantiate(&self) -> Result<(), InstantiationError> {
Ok(()) Ok(())
} }
/// Crate an `Instance` from this `Artifact`. /// Crate an `Instance` from this `Artifact`.
/// ///
/// # Safety /// # Safety
@@ -168,7 +120,6 @@ pub trait Artifact: Send + Sync + Upcastable + MemoryUsage {
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?; .map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))?;
Ok(handle) Ok(handle)
} }
/// Finishes the instantiation of a just created `InstanceHandle`. /// Finishes the instantiation of a just created `InstanceHandle`.
/// ///
/// # Safety /// # Safety
@@ -193,29 +144,6 @@ pub trait Artifact: Send + Sync + Upcastable + MemoryUsage {
} }
} }
// 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 {
fn upcast_any_ref(&'_ self) -> &'_ dyn Any;
fn upcast_any_mut(&'_ mut self) -> &'_ mut dyn Any;
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 Artifact + 'static { impl dyn Artifact + 'static {
/// Try to downcast the artifact into a given type. /// Try to downcast the artifact into a given type.
#[inline] #[inline]
@@ -229,67 +157,3 @@ impl dyn Artifact + 'static {
self.upcast_any_mut().downcast_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)
}
}

View File

@@ -1,60 +1,7 @@
//! The WebAssembly possible errors //! The WebAssembly possible errors
use crate::trap::RuntimeError; use crate::trap::RuntimeError;
use std::io;
use thiserror::Error; use thiserror::Error;
use wasmer_compiler::CompileError; pub use wasmer_artifact::{DeserializeError, ImportError, SerializeError};
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),
}
/// The WebAssembly.LinkError object indicates an error during /// The WebAssembly.LinkError object indicates an error during
/// module instantiation (besides traps from the start function). /// module instantiation (besides traps from the start function).

View File

@@ -31,11 +31,9 @@ mod resolver;
mod trap; mod trap;
mod tunables; mod tunables;
pub use crate::artifact::{Artifact, MetadataHeader}; pub use crate::artifact::Artifact;
pub use crate::engine::{Engine, EngineId}; pub use crate::engine::{Engine, EngineId};
pub use crate::error::{ pub use crate::error::{InstantiationError, LinkError};
DeserializeError, ImportError, InstantiationError, LinkError, SerializeError,
};
pub use crate::export::{Export, ExportFunction, ExportFunctionMetadata}; pub use crate::export::{Export, ExportFunction, ExportFunctionMetadata};
pub use crate::resolver::{ pub use crate::resolver::{
resolve_imports, ChainableNamedResolver, NamedResolver, NamedResolverChain, NullResolver, resolve_imports, ChainableNamedResolver, NamedResolver, NamedResolverChain, NullResolver,
@@ -43,6 +41,8 @@ pub use crate::resolver::{
}; };
pub use crate::trap::*; pub use crate::trap::*;
pub use crate::tunables::Tunables; pub use crate::tunables::Tunables;
pub use wasmer_artifact::{ArtifactCreate, MetadataHeader};
pub use wasmer_artifact::{DeserializeError, ImportError, SerializeError};
/// Version number of this crate. /// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");

View File

@@ -2,6 +2,7 @@ use enum_iterator::IntoEnumIterator;
use loupe::MemoryUsage; use loupe::MemoryUsage;
#[cfg(feature = "enable-rkyv")] #[cfg(feature = "enable-rkyv")]
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
@@ -12,9 +13,8 @@ use std::fmt;
feature = "enable-rkyv", feature = "enable-rkyv",
derive(RkyvSerialize, RkyvDeserialize, Archive) derive(RkyvSerialize, RkyvDeserialize, Archive)
)] )]
#[derive( #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, MemoryUsage, IntoEnumIterator, #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, MemoryUsage, IntoEnumIterator)]
)]
pub enum LibCall { pub enum LibCall {
/// ceil.f32 /// ceil.f32
CeilF32, CeilF32,

View File

@@ -2,6 +2,7 @@ use crate::Pages;
use loupe::MemoryUsage; use loupe::MemoryUsage;
#[cfg(feature = "enable-rkyv")] #[cfg(feature = "enable-rkyv")]
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use thiserror::Error; use thiserror::Error;
@@ -48,11 +49,12 @@ pub enum MemoryError {
} }
/// Implementation styles for WebAssembly linear memory. /// Implementation styles for WebAssembly linear memory.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, MemoryUsage)] #[derive(Debug, Clone, PartialEq, Eq, Hash, MemoryUsage)]
#[cfg_attr( #[cfg_attr(
feature = "enable-rkyv", feature = "enable-rkyv",
derive(RkyvSerialize, RkyvDeserialize, Archive) derive(RkyvSerialize, RkyvDeserialize, Archive)
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum MemoryStyle { pub enum MemoryStyle {
/// The actual memory can be resized and moved. /// The actual memory can be resized and moved.
Dynamic { Dynamic {

View File

@@ -1,14 +1,16 @@
use loupe::MemoryUsage; use loupe::MemoryUsage;
#[cfg(feature = "enable-rkyv")] #[cfg(feature = "enable-rkyv")]
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Implementation styles for WebAssembly tables. /// Implementation styles for WebAssembly tables.
#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, MemoryUsage)] #[derive(Debug, Clone, Hash, PartialEq, Eq, MemoryUsage)]
#[cfg_attr( #[cfg_attr(
feature = "enable-rkyv", feature = "enable-rkyv",
derive(RkyvSerialize, RkyvDeserialize, Archive) derive(RkyvSerialize, RkyvDeserialize, Archive)
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum TableStyle { pub enum TableStyle {
/// Signatures are stored in the table and checked in the caller. /// Signatures are stored in the table and checked in the caller.
CallerChecksSignature, CallerChecksSignature,

View File

@@ -9,6 +9,7 @@ use core::str::FromStr;
use loupe::MemoryUsage; use loupe::MemoryUsage;
#[cfg(feature = "enable-rkyv")] #[cfg(feature = "enable-rkyv")]
use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
use thiserror::Error; use thiserror::Error;
@@ -16,11 +17,12 @@ use thiserror::Error;
/// A trap code describing the reason for a trap. /// A trap code describing the reason for a trap.
/// ///
/// All trap instructions have an explicit trap code. /// All trap instructions have an explicit trap code.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize, Error, MemoryUsage)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Error, MemoryUsage)]
#[cfg_attr( #[cfg_attr(
feature = "enable-rkyv", feature = "enable-rkyv",
derive(RkyvSerialize, RkyvDeserialize, Archive) derive(RkyvSerialize, RkyvDeserialize, Archive)
)] )]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[repr(u32)] #[repr(u32)]
pub enum TrapCode { pub enum TrapCode {
/// The current stack space was exhausted. /// The current stack space was exhausted.

View File

@@ -12,6 +12,7 @@ edition = "2018"
[dependencies] [dependencies]
wasmer-types = { path = "../types", version = "=2.2.1" } wasmer-types = { path = "../types", version = "=2.2.1" }
wasmer-artifact = { path = "../artifact", version = "=2.2.1" }
libc = { version = "^0.2", default-features = false } libc = { version = "^0.2", default-features = false }
memoffset = "0.6" memoffset = "0.6"
indexmap = { version = "1.6", features = ["serde-1"] } indexmap = { version = "1.6", features = ["serde-1"] }

View File

@@ -50,12 +50,11 @@ pub use crate::sig_registry::SignatureRegistry;
pub use crate::table::{LinearTable, Table, TableElement}; pub use crate::table::{LinearTable, Table, TableElement};
pub use crate::trap::*; pub use crate::trap::*;
pub use crate::vmcontext::{ pub use crate::vmcontext::{
VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionBody, VMCallerCheckedAnyfunc, VMContext, VMDynamicFunctionContext, VMFunctionEnvironment,
VMFunctionEnvironment, VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMFunctionImport, VMFunctionKind, VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition,
VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition, VMTableImport, VMTrampoline,
VMTrampoline,
}; };
use loupe::MemoryUsage; pub use wasmer_artifact::{FunctionBodyPtr, VMFunctionBody};
pub use wasmer_types::LibCall; pub use wasmer_types::LibCall;
pub use wasmer_types::TableStyle; pub use wasmer_types::TableStyle;
#[deprecated( #[deprecated(
@@ -71,28 +70,6 @@ pub use wasmer_types::{
/// Version number of this crate. /// Version number of this crate.
pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const VERSION: &str = env!("CARGO_PKG_VERSION");
/// A safe wrapper around `VMFunctionBody`.
#[derive(Clone, Copy, Debug, MemoryUsage)]
#[repr(transparent)]
pub struct FunctionBodyPtr(pub *const VMFunctionBody);
impl std::ops::Deref for FunctionBodyPtr {
type Target = *const VMFunctionBody;
fn deref(&self) -> &Self::Target {
&self.0
}
}
/// # Safety
/// The VMFunctionBody that this points to is opaque, so there's no data to
/// read or write through this pointer. This is essentially a usize.
unsafe impl Send for FunctionBodyPtr {}
/// # Safety
/// The VMFunctionBody that this points to is opaque, so there's no data to
/// read or write through this pointer. This is essentially a usize.
unsafe impl Sync for FunctionBodyPtr {}
/// Pointers to section data. /// Pointers to section data.
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
#[repr(transparent)] #[repr(transparent)]

View File

@@ -20,6 +20,7 @@ use std::mem;
use std::ptr::{self, NonNull}; use std::ptr::{self, NonNull};
use std::sync::Arc; use std::sync::Arc;
use std::u32; use std::u32;
pub use wasmer_artifact::VMFunctionBody;
/// Union representing the first parameter passed when calling a function. /// Union representing the first parameter passed when calling a function.
/// ///
@@ -169,24 +170,6 @@ mod test_vmdynamicfunction_import_context {
} }
} }
/// 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);
}
}
/// A function kind is a calling convention into and out of wasm code. /// A function kind is a calling convention into and out of wasm code.
#[derive(Debug, Copy, Clone, PartialEq, MemoryUsage)] #[derive(Debug, Copy, Clone, PartialEq, MemoryUsage)]
#[repr(C)] #[repr(C)]
@@ -799,9 +782,8 @@ pub struct VMSharedSignatureIndex(u32);
#[cfg(test)] #[cfg(test)]
mod test_vmshared_signature_index { mod test_vmshared_signature_index {
use super::VMSharedSignatureIndex; use super::VMSharedSignatureIndex;
use crate::vmoffsets::{TargetSharedSignatureIndex, VMOffsets};
use std::mem::size_of; use std::mem::size_of;
use wasmer_types::ModuleInfo; use wasmer_types::{ModuleInfo, TargetSharedSignatureIndex, VMOffsets};
#[test] #[test]
fn check_vmshared_signature_index() { fn check_vmshared_signature_index() {

View File

@@ -8,6 +8,7 @@ edition = "2018"
publish = false publish = false
[dependencies] [dependencies]
wasmer-artifact = { path = "../../../lib/artifact", version = "=2.2.1" }
wasmer-types = { path = "../../../lib/types", version = "=2.2.1" } wasmer-types = { path = "../../../lib/types", version = "=2.2.1" }
wasmer-compiler = { path = "../../../lib/compiler", version = "=2.2.1" } wasmer-compiler = { path = "../../../lib/compiler", version = "=2.2.1" }
wasmer-vm = { path = "../../../lib/vm", version = "=2.2.1" } wasmer-vm = { path = "../../../lib/vm", version = "=2.2.1" }

View File

@@ -7,6 +7,7 @@ use loupe::MemoryUsage;
#[cfg(feature = "serialize")] #[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use wasmer_artifact::ArtifactCreate;
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
use wasmer_compiler::ModuleEnvironment; use wasmer_compiler::ModuleEnvironment;
use wasmer_compiler::{CompileError, CpuFeature}; use wasmer_compiler::{CompileError, CpuFeature};
@@ -193,7 +194,7 @@ impl DummyArtifact {
} }
} }
impl Artifact for DummyArtifact { impl ArtifactCreate for DummyArtifact {
fn module(&self) -> Arc<ModuleInfo> { fn module(&self) -> Arc<ModuleInfo> {
self.metadata.module.clone() self.metadata.module.clone()
} }
@@ -229,7 +230,25 @@ impl Artifact for DummyArtifact {
fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> { fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
&self.metadata.table_styles &self.metadata.table_styles
} }
#[cfg(feature = "serialize")]
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
let bytes = bincode::serialize(&self.metadata)
.map_err(|e| SerializeError::Generic(format!("{:?}", e)))?;
// Prepend the header.
let mut serialized = Self::MAGIC_HEADER.to_vec();
serialized.extend(bytes);
Ok(serialized)
}
#[cfg(not(feature = "serialize"))]
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
Err(SerializeError::Generic(
"The serializer feature is not enabled in the DummyEngine",
))
}
}
impl Artifact for DummyArtifact {
fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> { fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
&self.finished_functions &self.finished_functions
} }
@@ -249,22 +268,4 @@ impl Artifact for DummyArtifact {
fn func_data_registry(&self) -> &FuncDataRegistry { fn func_data_registry(&self) -> &FuncDataRegistry {
&self.func_data_registry &self.func_data_registry
} }
#[cfg(feature = "serialize")]
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
let bytes = bincode::serialize(&self.metadata)
.map_err(|e| SerializeError::Generic(format!("{:?}", e)))?;
// Prepend the header.
let mut serialized = Self::MAGIC_HEADER.to_vec();
serialized.extend(bytes);
Ok(serialized)
}
#[cfg(not(feature = "serialize"))]
fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
Err(SerializeError::Generic(
"The serializer feature is not enabled in the DummyEngine",
))
}
} }