diff --git a/Cargo.lock b/Cargo.lock index f89f252b991..9b46ee31b3b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1723,9 +1723,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d683f1540522e9ad21b786d534b274ff49b0e974bf3af31d7a930a6c3e3599d" +checksum = "533488e35e9756976c402485db01485a3d5f51b46dd85cca9211b57373581cfa" dependencies = [ "memoffset", "ptr_meta", @@ -2573,7 +2573,6 @@ name = "wasmer-engine" version = "1.0.2" dependencies = [ "backtrace", - "bincode", "lazy_static", "loupe", "memmap2", @@ -2606,12 +2605,11 @@ dependencies = [ name = "wasmer-engine-jit" version = "1.0.2" dependencies = [ - "bincode", "cfg-if 0.1.10", + "leb128", "loupe", "region", - "serde", - "serde_bytes", + "rkyv", "wasmer-compiler", "wasmer-engine", "wasmer-types", @@ -2623,7 +2621,6 @@ dependencies = [ name = "wasmer-engine-native" version = "1.0.2" dependencies = [ - "bincode", "cfg-if 0.1.10", "leb128", "libloading", diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 3bb33ef7171..9537900b0e5 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -61,16 +61,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bincode" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d175dfa69e619905c4c3cdb7c3c203fa3bdd5d51184e3afdb2742c0280493772" -dependencies = [ - "byteorder", - "serde", -] - [[package]] name = "bitflags" version = "1.2.1" @@ -844,9 +834,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d683f1540522e9ad21b786d534b274ff49b0e974bf3af31d7a930a6c3e3599d" +checksum = "533488e35e9756976c402485db01485a3d5f51b46dd85cca9211b57373581cfa" dependencies = [ "memoffset", "ptr_meta", @@ -1261,7 +1251,6 @@ name = "wasmer-engine" version = "1.0.2" dependencies = [ "backtrace", - "bincode", "lazy_static", "loupe", "memmap2", @@ -1280,12 +1269,11 @@ dependencies = [ name = "wasmer-engine-jit" version = "1.0.2" dependencies = [ - "bincode", "cfg-if 0.1.10", + "leb128", "loupe", "region", - "serde", - "serde_bytes", + "rkyv", "wasmer-compiler", "wasmer-engine", "wasmer-types", @@ -1297,7 +1285,6 @@ dependencies = [ name = "wasmer-engine-native" version = "1.0.2" dependencies = [ - "bincode", "cfg-if 0.1.10", "leb128", "libloading", diff --git a/lib/compiler/Cargo.toml b/lib/compiler/Cargo.toml index 911710002df..11912098acb 100644 --- a/lib/compiler/Cargo.toml +++ b/lib/compiler/Cargo.toml @@ -21,7 +21,7 @@ serde = { version = "1.0", features = ["derive"], optional = true } thiserror = "1.0" serde_bytes = { version = "0.11", optional = true } smallvec = "1.6" -rkyv = { version = "0.6", optional = true } +rkyv = { version = "0.6.1", optional = true } loupe = "0.1" [features] @@ -33,7 +33,7 @@ translator = ["wasmparser"] std = ["wasmer-types/std"] core = ["hashbrown", "wasmer-types/core"] enable-serde = ["serde", "serde_bytes", "wasmer-types/enable-serde"] -enable-rkyv = ["rkyv", "wasmer-vm/enable-rkyv"] +enable-rkyv = ["rkyv", "wasmer-vm/enable-rkyv", "wasmer-types/enable-rkyv"] [badges] maintenance = { status = "experimental" } diff --git a/lib/compiler/src/address_map.rs b/lib/compiler/src/address_map.rs index 4fd8c1a2396..74db48dcba5 100644 --- a/lib/compiler/src/address_map.rs +++ b/lib/compiler/src/address_map.rs @@ -4,11 +4,17 @@ use crate::lib::std::vec::Vec; use crate::sourceloc::SourceLoc; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; /// Single source location to generated address mapping. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, MemoryUsage)] pub struct InstructionAddressMap { /// Original source location. @@ -23,6 +29,10 @@ pub struct InstructionAddressMap { /// Function and its instructions addresses mappings. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, Default, MemoryUsage)] pub struct FunctionAddressMap { /// Instructions maps. diff --git a/lib/compiler/src/function.rs b/lib/compiler/src/function.rs index e431f3bb7e0..98be7a63255 100644 --- a/lib/compiler/src/function.rs +++ b/lib/compiler/src/function.rs @@ -13,6 +13,8 @@ use crate::section::{CustomSection, SectionIndex}; use crate::trap::TrapInformation; use crate::{CompiledFunctionUnwindInfo, FunctionAddressMap, JumpTableOffsets, Relocation}; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use wasmer_types::entity::PrimaryMap; @@ -23,6 +25,10 @@ use wasmer_types::{FunctionIndex, LocalFunctionIndex, SignatureIndex}; /// This structure is only used for reconstructing /// the frame information after a `Trap`. #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, Default, MemoryUsage)] pub struct CompiledFunctionFrameInfo { /// The traps (in the function body). @@ -36,6 +42,10 @@ pub struct CompiledFunctionFrameInfo { /// The function body. #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, MemoryUsage)] pub struct FunctionBody { /// The function body bytes. @@ -52,6 +62,10 @@ pub struct FunctionBody { /// (function bytecode body, relocations, traps, jump tables /// and unwind information). #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq)] pub struct CompiledFunction { /// The function body. @@ -80,6 +94,10 @@ pub type CustomSections = PrimaryMap; /// In the future this structure may also hold other information useful /// for debugging. #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, PartialEq, Eq, Clone, MemoryUsage)] pub struct Dwarf { /// The section index in the [`Compilation`] that corresponds to the exception frames. diff --git a/lib/compiler/src/jump_table.rs b/lib/compiler/src/jump_table.rs index 25fdbb60c08..5fc7551bb6b 100644 --- a/lib/compiler/src/jump_table.rs +++ b/lib/compiler/src/jump_table.rs @@ -6,6 +6,8 @@ use super::CodeOffset; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use wasmer_types::entity::{entity_impl, SecondaryMap}; @@ -15,6 +17,10 @@ use wasmer_types::entity::{entity_impl, SecondaryMap}; /// `JumpTable`s are used for indirect branching and are specialized for dense, /// 0-based jump offsets. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, MemoryUsage)] pub struct JumpTable(u32); diff --git a/lib/compiler/src/relocation.rs b/lib/compiler/src/relocation.rs index 25cec340ad9..1a02c9198a0 100644 --- a/lib/compiler/src/relocation.rs +++ b/lib/compiler/src/relocation.rs @@ -14,6 +14,8 @@ use crate::lib::std::vec::Vec; use crate::section::SectionIndex; use crate::{Addend, CodeOffset, JumpTable}; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use wasmer_types::entity::PrimaryMap; @@ -22,6 +24,10 @@ use wasmer_vm::libcalls::LibCall; /// Relocation kinds for every ISA. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Copy, Clone, Debug, PartialEq, Eq, MemoryUsage)] pub enum RelocationKind { /// absolute 4-byte @@ -80,6 +86,10 @@ impl fmt::Display for RelocationKind { /// A record of a relocation to perform. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, MemoryUsage)] pub struct Relocation { /// The relocation kind. @@ -94,6 +104,10 @@ pub struct Relocation { /// Destination function. Can be either user function or some special one, like `memory.grow`. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Copy, Clone, PartialEq, Eq, MemoryUsage)] pub enum RelocationTarget { /// A relocation to a function defined locally in the wasm (not an imported one). diff --git a/lib/compiler/src/section.rs b/lib/compiler/src/section.rs index f6f3ee40484..98063705d99 100644 --- a/lib/compiler/src/section.rs +++ b/lib/compiler/src/section.rs @@ -8,21 +8,38 @@ use crate::lib::std::vec::Vec; use crate::Relocation; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use wasmer_types::entity::entity_impl; /// Index type of a Section defined inside a WebAssembly `Compilation`. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] +#[cfg_attr( + feature = "enable-rkyv", + archive(derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)) +)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug, MemoryUsage)] pub struct SectionIndex(u32); entity_impl!(SectionIndex); +#[cfg(feature = "enable-rkyv")] +entity_impl!(ArchivedSectionIndex); + /// Custom section Protection. /// /// Determines how a custom section may be used. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, MemoryUsage)] pub enum CustomSectionProtection { /// A custom section with read permission. @@ -37,6 +54,10 @@ pub enum CustomSectionProtection { /// This is used so compilers can store arbitrary information /// in the emitted module. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, MemoryUsage)] pub struct CustomSection { /// Memory protection that applies to this section. @@ -56,6 +77,10 @@ pub struct CustomSection { /// The bytes in the section. #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, Default, MemoryUsage)] pub struct SectionBody(#[cfg_attr(feature = "enable-serde", serde(with = "serde_bytes"))] Vec); diff --git a/lib/compiler/src/sourceloc.rs b/lib/compiler/src/sourceloc.rs index fa61e4ab897..5874cd4f4db 100644 --- a/lib/compiler/src/sourceloc.rs +++ b/lib/compiler/src/sourceloc.rs @@ -9,6 +9,8 @@ use crate::lib::std::fmt; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; @@ -21,6 +23,10 @@ use serde::{Deserialize, Serialize}; derive(Serialize, Deserialize), serde(transparent) )] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq, MemoryUsage)] pub struct SourceLoc(u32); diff --git a/lib/compiler/src/trap.rs b/lib/compiler/src/trap.rs index 80aecc73a3b..2d016c13122 100644 --- a/lib/compiler/src/trap.rs +++ b/lib/compiler/src/trap.rs @@ -1,11 +1,17 @@ use crate::CodeOffset; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use wasmer_vm::TrapCode; /// Information about trap. #[cfg_attr(feature = "enable-serde", derive(Deserialize, Serialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Clone, Debug, PartialEq, Eq, MemoryUsage)] pub struct TrapInformation { /// The offset of the trapping instruction in native code. It is relative to the beginning of the function. diff --git a/lib/compiler/src/unwind.rs b/lib/compiler/src/unwind.rs index 128c300deab..ec344a9c15e 100644 --- a/lib/compiler/src/unwind.rs +++ b/lib/compiler/src/unwind.rs @@ -7,6 +7,8 @@ //! [Learn more](https://en.wikipedia.org/wiki/Call_stack). use crate::lib::std::vec::Vec; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; @@ -18,6 +20,10 @@ use serde::{Deserialize, Serialize}; /// /// [unwind info]: https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=vs-2019 #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Debug, Clone, PartialEq, Eq, MemoryUsage)] pub enum CompiledFunctionUnwindInfo { /// Windows UNWIND_INFO. diff --git a/lib/engine-jit/Cargo.toml b/lib/engine-jit/Cargo.toml index 519a324c7ac..96399200d82 100644 --- a/lib/engine-jit/Cargo.toml +++ b/lib/engine-jit/Cargo.toml @@ -11,16 +11,15 @@ readme = "README.md" edition = "2018" [dependencies] -wasmer-types = { path = "../types", version = "1.0.2" } -wasmer-compiler = { path = "../compiler", version = "1.0.2", features = ["translator"] } -wasmer-vm = { path = "../vm", version = "1.0.2" } +wasmer-types = { path = "../types", version = "1.0.2", features = ["enable-rkyv"] } +wasmer-compiler = { path = "../compiler", version = "1.0.2", features = ["translator", "enable-rkyv"] } +wasmer-vm = { path = "../vm", version = "1.0.2", features = ["enable-rkyv"] } wasmer-engine = { path = "../engine", version = "1.0.2" } # flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" } region = "2.2" -serde = { version = "1.0", features = ["derive", "rc"] } -serde_bytes = { version = "0.11" } -bincode = "1.3" cfg-if = "0.1" +leb128 = "0.2" +rkyv = "0.6.1" loupe = "0.1" [target.'cfg(target_os = "windows")'.dependencies] diff --git a/lib/engine-jit/src/artifact.rs b/lib/engine-jit/src/artifact.rs index 9b8a6c3d803..1bc1c5e005f 100644 --- a/lib/engine-jit/src/artifact.rs +++ b/lib/engine-jit/src/artifact.rs @@ -16,7 +16,7 @@ use wasmer_engine::{ SerializeError, }; #[cfg(feature = "compiler")] -use wasmer_engine::{Engine, SerializableFunctionFrameInfo, Tunables}; +use wasmer_engine::{Engine, Tunables}; use wasmer_types::entity::{BoxedSlice, PrimaryMap}; use wasmer_types::{ FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, SignatureIndex, @@ -27,6 +27,9 @@ use wasmer_vm::{ VMTrampoline, }; +const SERIALIZED_METADATA_LENGTH_OFFSET: usize = 16; +const SERIALIZED_METADATA_CONTENT_OFFSET: usize = 32; + /// A compiled wasm module, ready to be instantiated. #[derive(MemoryUsage)] pub struct JITArtifact { @@ -42,7 +45,7 @@ pub struct JITArtifact { } impl JITArtifact { - const MAGIC_HEADER: &'static [u8] = b"\0wasmer-jit"; + const MAGIC_HEADER: &'static [u8; 16] = b"\0wasmer-jit\0\0\0\0\0"; /// Check if the provided bytes look like a serialized `JITArtifact`. pub fn is_deserializable(bytes: &[u8]) -> bool { @@ -107,11 +110,7 @@ impl JITArtifact { .collect::>() .into_boxed_slice(); - let frame_infos = compilation - .get_frame_info() - .values() - .map(|frame_info| SerializableFunctionFrameInfo::Processed(frame_info.clone())) - .collect::>(); + let frame_infos = compilation.get_frame_info(); let serializable_compilation = SerializableCompilation { function_bodies: compilation.get_function_bodies(), @@ -141,21 +140,28 @@ impl JITArtifact { } /// Deserialize a JITArtifact - pub fn deserialize(jit: &JITEngine, bytes: &[u8]) -> Result { + /// + /// # Safety + /// This function is unsafe because rkyv reads directly without validating + /// the data. + pub unsafe fn deserialize(jit: &JITEngine, bytes: &[u8]) -> Result { if !Self::is_deserializable(bytes) { return Err(DeserializeError::Incompatible( "The provided bytes are not wasmer-jit".to_string(), )); } - let inner_bytes = &bytes[Self::MAGIC_HEADER.len()..]; + let mut inner_bytes = &bytes[SERIALIZED_METADATA_LENGTH_OFFSET..]; - // let r = flexbuffers::Reader::get_root(bytes).map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))?; - // let serializable = SerializableModule::deserialize(r).map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))?; - - let serializable: SerializableModule = bincode::deserialize(inner_bytes) - .map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))?; + let metadata_len = leb128::read::unsigned(&mut inner_bytes).map_err(|_e| { + DeserializeError::CorruptedBinary("Can't read metadata size".to_string()) + })?; + let metadata_slice: &[u8] = std::slice::from_raw_parts( + &bytes[SERIALIZED_METADATA_CONTENT_OFFSET] as *const u8, + metadata_len as usize, + ); + let serializable = SerializableModule::deserialize(metadata_slice)?; Self::from_parts(&mut jit.inner_mut(), serializable).map_err(DeserializeError::Compiler) } @@ -325,15 +331,51 @@ impl Artifact for JITArtifact { &self.func_data_registry } fn serialize(&self) -> Result, SerializeError> { - // let mut s = flexbuffers::FlexbufferSerializer::new(); - // self.serializable.serialize(&mut s).map_err(|e| SerializeError::Generic(format!("{:?}", e))); - // Ok(s.take_buffer()) - let bytes = bincode::serialize(&self.serializable) - .map_err(|e| SerializeError::Generic(format!("{:?}", e)))?; - // Prepend the header. let mut serialized = Self::MAGIC_HEADER.to_vec(); - serialized.extend(bytes); + + serialized.resize(SERIALIZED_METADATA_CONTENT_OFFSET, 0); + let mut writable_leb = &mut serialized[SERIALIZED_METADATA_LENGTH_OFFSET..]; + let serialized_data = self.serializable.serialize()?; + let length = serialized_data.len(); + leb128::write::unsigned(&mut writable_leb, length as u64).expect("Should write number"); + + let offset = pad_and_extend::(&mut serialized, &serialized_data); + assert_eq!(offset, SERIALIZED_METADATA_CONTENT_OFFSET); + Ok(serialized) } } + +/// It pads the data with the desired alignment +pub fn pad_and_extend(prev_data: &mut Vec, data: &[u8]) -> usize { + let align = std::mem::align_of::(); + + let mut offset = prev_data.len(); + if offset & (align - 1) != 0 { + offset += align - (offset & (align - 1)); + prev_data.resize(offset, 0); + } + prev_data.extend(data); + offset +} + +#[cfg(test)] +mod tests { + use super::pad_and_extend; + + #[test] + fn test_pad_and_extend() { + let mut data: Vec = vec![]; + let offset = pad_and_extend::(&mut data, &[1, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(offset, 0); + let offset = pad_and_extend::(&mut data, &[2, 0, 0, 0]); + assert_eq!(offset, 8); + let offset = pad_and_extend::(&mut data, &[3, 0, 0, 0, 0, 0, 0, 0]); + assert_eq!(offset, 16); + assert_eq!( + data, + &[1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0] + ); + } +} diff --git a/lib/engine-jit/src/serialize.rs b/lib/engine-jit/src/serialize.rs index c924381b9a0..3514bade518 100644 --- a/lib/engine-jit/src/serialize.rs +++ b/lib/engine-jit/src/serialize.rs @@ -1,33 +1,26 @@ use loupe::MemoryUsage; -use serde::{Deserialize, Serialize}; +use rkyv::{ + archived_value, + de::{adapters::SharedDeserializerAdapter, deserializers::AllocDeserializer}, + ser::adapters::SharedSerializerAdapter, + ser::{serializers::WriteSerializer, Serializer as RkyvSerializer}, + Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize, +}; use wasmer_compiler::{ - CompileModuleInfo, CustomSection, Dwarf, FunctionBody, JumpTableOffsets, Relocation, - SectionIndex, + CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody, + JumpTableOffsets, Relocation, SectionIndex, }; -use wasmer_engine::SerializableFunctionFrameInfo; +use wasmer_engine::{DeserializeError, SerializeError}; use wasmer_types::entity::PrimaryMap; use wasmer_types::{FunctionIndex, LocalFunctionIndex, OwnedDataInitializer, SignatureIndex}; -// /// The serializable function data -// #[derive(Serialize, Deserialize)] -// pub struct SerializableFunction { -// #[serde(with = "serde_bytes")] -// pub body: &[u8], -// /// The unwind info for Windows -// #[serde(with = "serde_bytes")] -// pub windows_unwind_info: &[u8], -// } - /// The compilation related data for a serialized modules -#[derive(Serialize, Deserialize, MemoryUsage)] +#[derive(MemoryUsage, Archive, RkyvDeserialize, RkyvSerialize)] pub struct SerializableCompilation { pub function_bodies: PrimaryMap, pub function_relocations: PrimaryMap>, pub function_jt_offsets: PrimaryMap, - // This is `SerializableFunctionFrameInfo` instead of `CompiledFunctionFrameInfo`, - // to allow lazy frame_info deserialization, we convert it to it's lazy binary - // format upon serialization. - pub function_frame_info: PrimaryMap, + pub function_frame_info: PrimaryMap, pub function_call_trampolines: PrimaryMap, pub dynamic_function_trampolines: PrimaryMap, pub custom_sections: PrimaryMap, @@ -38,9 +31,95 @@ pub struct SerializableCompilation { /// Serializable struct that is able to serialize from and to /// a `JITArtifactInfo`. -#[derive(Serialize, Deserialize, MemoryUsage)] +#[derive(MemoryUsage, Archive, RkyvDeserialize, RkyvSerialize)] pub struct SerializableModule { pub compilation: SerializableCompilation, pub compile_info: CompileModuleInfo, pub data_initializers: Box<[OwnedDataInitializer]>, } + +fn to_serialize_error(err: impl std::error::Error) -> SerializeError { + SerializeError::Generic(format!("{}", err)) +} + +cfg_if::cfg_if! { + if #[cfg(target_endian = "big")] { + const HOST_ENDIAN: u8 = b'b'; + } else if #[cfg(target_endian = "little")] { + const HOST_ENDIAN: u8 = b'l'; + } + else { + compile_error!("Endian not supported by the host"); + } +} + +impl SerializableModule { + /// Serialize a Module into bytes + /// The bytes will have the following format: + /// RKYV serialization (any length) + POS (8 bytes) + Endian (1 byte) + pub fn serialize(&self) -> Result, SerializeError> { + let mut serializer = SharedSerializerAdapter::new(WriteSerializer::new(vec![])); + let pos = serializer + .serialize_value(self) + .map_err(to_serialize_error)? as u64; + let mut serialized_data = serializer.into_inner().into_inner(); + serialized_data.extend_from_slice(&pos.to_le_bytes()); + serialized_data.extend_from_slice(&[HOST_ENDIAN]); + Ok(serialized_data) + } + + /// Deserialize a Module from a slice. + /// The slice must have the following format: + /// RKYV serialization (any length) + POS (8 bytes) + Endian (1 byte) + /// + /// # Safety + /// + /// This method is unsafe since it deserializes data directly + /// from memory. + /// Right now we are not doing any extra work for validation, but + /// `rkyv` has an option to do bytecheck on the serialized data before + /// serializing (via `rkyv::check_archived_value`). + pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result { + let archived = Self::archive_from_slice(metadata_slice)?; + Self::deserialize_from_archive(archived) + } + + /// # Safety + /// + /// This method is unsafe. + /// Please check `SerializableModule::deserialize` for more details. + unsafe fn archive_from_slice<'a>( + metadata_slice: &'a [u8], + ) -> Result<&'a ArchivedSerializableModule, DeserializeError> { + if metadata_slice.len() < 9 { + return Err(DeserializeError::Incompatible( + "invalid serialized data".into(), + )); + } + let mut pos: [u8; 8] = Default::default(); + let endian = metadata_slice[metadata_slice.len() - 1]; + if endian != HOST_ENDIAN { + return Err(DeserializeError::Incompatible( + format!( + "incompatible endian. Received {} but expected {}", + endian, HOST_ENDIAN + ) + .into(), + )); + } + pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 9..metadata_slice.len() - 1]); + let pos: u64 = u64::from_le_bytes(pos); + Ok(archived_value::( + &metadata_slice[..metadata_slice.len() - 9], + pos as usize, + )) + } + + pub fn deserialize_from_archive( + archived: &ArchivedSerializableModule, + ) -> Result { + let mut deserializer = SharedDeserializerAdapter::new(AllocDeserializer); + RkyvDeserialize::deserialize(archived, &mut deserializer) + .map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e))) + } +} diff --git a/lib/engine-native/Cargo.toml b/lib/engine-native/Cargo.toml index 4d7f1c699d6..2919c1d4b94 100644 --- a/lib/engine-native/Cargo.toml +++ b/lib/engine-native/Cargo.toml @@ -19,12 +19,11 @@ wasmer-object = { path = "../object", version = "1.0.2" } serde = { version = "1.0", features = ["derive", "rc"] } cfg-if = "0.1" tracing = "0.1" -bincode = "1.3" leb128 = "0.2" libloading = "0.7" tempfile = "3.1" which = "4.0" -rkyv = "0.6" +rkyv = "0.6.1" loupe = "0.1" [features] diff --git a/lib/engine-native/src/artifact.rs b/lib/engine-native/src/artifact.rs index 06cfd2fe465..c95e70e8e5f 100644 --- a/lib/engine-native/src/artifact.rs +++ b/lib/engine-native/src/artifact.rs @@ -195,7 +195,7 @@ impl NativeArtifact { let serialized_data = metadata.serialize()?; - let mut metadata_binary = vec![0; 16]; + let mut metadata_binary = vec![0; 12]; let mut writable = &mut metadata_binary[..]; leb128::write::unsigned(&mut writable, serialized_data.len() as u64) .expect("Should write number"); @@ -543,11 +543,11 @@ impl NativeArtifact { DeserializeError::CorruptedBinary(format!("Library loading failed: {}", e)) })?; let shared_path: PathBuf = PathBuf::from(path); - // We use 16 + 1, as the length of the module will take 16 bytes + // We use 12 + 1, as the length of the module will take 12 bytes // (we construct it like that in `metadata_length`) and we also want // to take the first element of the data to construct the slice from // it. - let symbol: LibrarySymbol<*mut [u8; 16 + 1]> = + let symbol: LibrarySymbol<*mut [u8; 12 + 1]> = lib.get(WASMER_METADATA_SYMBOL).map_err(|e| { DeserializeError::CorruptedBinary(format!( "The provided object file doesn't seem to be generated by Wasmer: {}", @@ -563,7 +563,7 @@ impl NativeArtifact { DeserializeError::CorruptedBinary("Can't read metadata size".to_string()) })?; let metadata_slice: &'static [u8] = - slice::from_raw_parts(&size[16] as *const u8, metadata_len as usize); + slice::from_raw_parts(&size[12] as *const u8, metadata_len as usize); let metadata = ModuleMetadata::deserialize(metadata_slice)?; diff --git a/lib/engine/Cargo.toml b/lib/engine/Cargo.toml index 81ea2b18f08..83d80f9c70d 100644 --- a/lib/engine/Cargo.toml +++ b/lib/engine/Cargo.toml @@ -23,7 +23,6 @@ more-asserts = "0.2" thiserror = "1.0" serde = { version = "1.0", features = ["derive", "rc"] } serde_bytes = { version = "0.11" } -bincode = "1.3" lazy_static = "1.4" loupe = "0.1" diff --git a/lib/engine/src/lib.rs b/lib/engine/src/lib.rs index e5754535823..203d84e868b 100644 --- a/lib/engine/src/lib.rs +++ b/lib/engine/src/lib.rs @@ -25,7 +25,6 @@ mod engine; mod error; mod export; mod resolver; -mod serialize; mod trap; mod tunables; @@ -41,7 +40,6 @@ pub use crate::resolver::{ resolve_imports, ChainableNamedResolver, NamedResolver, NamedResolverChain, NullResolver, Resolver, }; -pub use crate::serialize::SerializableFunctionFrameInfo; pub use crate::trap::*; pub use crate::tunables::Tunables; diff --git a/lib/engine/src/serialize.rs b/lib/engine/src/serialize.rs deleted file mode 100644 index a36b47da320..00000000000 --- a/lib/engine/src/serialize.rs +++ /dev/null @@ -1,105 +0,0 @@ -use loupe::MemoryUsage; -use serde::de::{Deserializer, Visitor}; -use serde::ser::Serializer; -use serde::{Deserialize, Serialize}; -use std::fmt; -use wasmer_compiler::CompiledFunctionFrameInfo; - -/// This is the unserialized verison of `CompiledFunctionFrameInfo`. -#[derive(Clone, Serialize, Deserialize, MemoryUsage)] -#[serde(transparent)] -#[repr(transparent)] -pub struct UnprocessedFunctionFrameInfo { - #[serde(with = "serde_bytes")] - bytes: Vec, -} - -impl UnprocessedFunctionFrameInfo { - /// Converts the `UnprocessedFunctionFrameInfo` to a `CompiledFunctionFrameInfo` - pub fn deserialize(&self) -> CompiledFunctionFrameInfo { - // let r = flexbuffers::Reader::get_root(&self.bytes).expect("Can't deserialize the info"); - // CompiledFunctionFrameInfo::deserialize(r).expect("Can't deserialize the info") - bincode::deserialize(&self.bytes).expect("Can't deserialize the info") - } - - /// Converts the `CompiledFunctionFrameInfo` to a `UnprocessedFunctionFrameInfo` - pub fn serialize(processed: &CompiledFunctionFrameInfo) -> Self { - // let mut s = flexbuffers::FlexbufferSerializer::new(); - // processed - // .serialize(&mut s) - // .expect("Can't serialize the info"); - // let bytes = s.take_buffer(); - let bytes = bincode::serialize(&processed).expect("Can't serialize the info"); - Self { bytes } - } -} - -/// We hold the frame info in two states, mainly because we want to -/// process it lazily to speed up execution. -/// -/// When a Trap occurs, we process the frame info lazily for each -/// function in the frame. That way we minimize as much as we can -/// the upfront effort. -/// -/// The data can also be processed upfront. This will happen in the case -/// of compiling at the same time that emiting the JIT. -/// In that case, we don't need to deserialize/process anything -/// as the data is already in memory. -#[derive(Clone, MemoryUsage)] -pub enum SerializableFunctionFrameInfo { - /// The unprocessed frame info (binary) - Unprocessed(UnprocessedFunctionFrameInfo), - /// The processed frame info (memory struct) - Processed(CompiledFunctionFrameInfo), -} - -impl SerializableFunctionFrameInfo { - /// Returns true if the extra function info is not yet - /// processed - pub fn is_unprocessed(&self) -> bool { - matches!(self, Self::Unprocessed(_)) - } -} - -// Below: -// The custom ser/de for `SerializableFunctionFrameInfo`. - -impl Serialize for SerializableFunctionFrameInfo { - fn serialize(&self, s: S) -> Result - where - S: Serializer, - { - let unprocessed = match self { - Self::Processed(processed) => UnprocessedFunctionFrameInfo::serialize(processed), - Self::Unprocessed(unprocessed) => unprocessed.clone(), - }; - s.serialize_bytes(&unprocessed.bytes) - } -} - -struct FunctionFrameInfoVisitor; - -impl<'de> Visitor<'de> for FunctionFrameInfoVisitor { - type Value = UnprocessedFunctionFrameInfo; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("bytes") - } - fn visit_byte_buf(self, v: Vec) -> Result { - Ok(UnprocessedFunctionFrameInfo { bytes: v }) - } - fn visit_bytes(self, v: &[u8]) -> Result { - Ok(UnprocessedFunctionFrameInfo { bytes: v.to_vec() }) - } -} - -impl<'de> Deserialize<'de> for SerializableFunctionFrameInfo { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Ok(Self::Unprocessed( - deserializer.deserialize_byte_buf(FunctionFrameInfoVisitor)?, - )) - } -} diff --git a/lib/engine/src/trap/error.rs b/lib/engine/src/trap/error.rs index 36cdb7e49bc..98c2effeb94 100644 --- a/lib/engine/src/trap/error.rs +++ b/lib/engine/src/trap/error.rs @@ -3,7 +3,6 @@ use backtrace::Backtrace; use std::error::Error; use std::fmt; use std::sync::Arc; -use std::sync::RwLockReadGuard; use wasmer_vm::{raise_user_trap, Trap, TrapCode}; /// A struct representing an aborted instruction execution, with a message @@ -56,7 +55,7 @@ impl RuntimeError { let info = FRAME_INFO.read().unwrap(); let msg = message.into(); Self::new_with_trace( - info, + &info, None, RuntimeErrorSource::Generic(msg), Backtrace::new_unresolved(), @@ -72,7 +71,7 @@ impl RuntimeError { // The error is already a RuntimeError, we return it directly Ok(runtime_error) => *runtime_error, Err(e) => Self::new_with_trace( - info, + &info, None, RuntimeErrorSource::User(e), Backtrace::new_unresolved(), @@ -85,27 +84,18 @@ impl RuntimeError { signal_trap, backtrace, } => { - let info = if info.should_process_frame(pc).unwrap_or(false) { - drop(info); - let mut info = FRAME_INFO.write().unwrap(); - info.maybe_process_frame(pc).unwrap(); - drop(info); - FRAME_INFO.read().unwrap() - } else { - info - }; let code = info .lookup_trap_info(pc) .map_or(signal_trap.unwrap_or(TrapCode::StackOverflow), |info| { info.trap_code }); - Self::new_with_trace(info, Some(pc), RuntimeErrorSource::Trap(code), backtrace) + Self::new_with_trace(&info, Some(pc), RuntimeErrorSource::Trap(code), backtrace) } // A trap triggered manually from the Wasmer runtime Trap::Runtime { trap_code, backtrace, - } => Self::new_with_trace(info, None, RuntimeErrorSource::Trap(trap_code), backtrace), + } => Self::new_with_trace(&info, None, RuntimeErrorSource::Trap(trap_code), backtrace), } } @@ -115,7 +105,7 @@ impl RuntimeError { } fn new_with_trace( - info: RwLockReadGuard, + info: &GlobalFrameInfo, trap_pc: Option, source: RuntimeErrorSource, native_trace: Backtrace, @@ -144,28 +134,6 @@ impl RuntimeError { }) .collect(); - // If any of the frames is not processed, we adquire the lock to - // modify the GlobalFrameInfo module. - let info = if frames - .iter() - .any(|pc| info.should_process_frame(*pc).unwrap_or(false)) - { - // We drop the read lock, to get a write one. - // Note: this is not guaranteed because it's a RwLock: - // the following code may cause deadlocks. - // TODO: clean up this code - drop(info); - { - let mut info = FRAME_INFO.write().unwrap(); - for pc in frames.iter() { - info.maybe_process_frame(*pc); - } - } - FRAME_INFO.read().unwrap() - } else { - info - }; - // Let's construct the trace let wasm_trace = frames .into_iter() diff --git a/lib/engine/src/trap/frame_info.rs b/lib/engine/src/trap/frame_info.rs index 3407ab742db..cb155ada5b0 100644 --- a/lib/engine/src/trap/frame_info.rs +++ b/lib/engine/src/trap/frame_info.rs @@ -10,7 +10,6 @@ //! let module: ModuleInfo = ...; //! FRAME_INFO.register(module, compiled_functions); //! ``` -use crate::serialize::SerializableFunctionFrameInfo; use loupe::MemoryUsage; use std::cmp; use std::collections::BTreeMap; @@ -56,39 +55,14 @@ struct ModuleInfoFrameInfo { start: usize, functions: BTreeMap, module: Arc, - frame_infos: PrimaryMap, + frame_infos: PrimaryMap, } impl ModuleInfoFrameInfo { - fn function_debug_info( - &self, - local_index: LocalFunctionIndex, - ) -> &SerializableFunctionFrameInfo { + fn function_debug_info(&self, local_index: LocalFunctionIndex) -> &CompiledFunctionFrameInfo { &self.frame_infos.get(local_index).unwrap() } - fn process_function_debug_info(&mut self, local_index: LocalFunctionIndex) { - let func = self.frame_infos.get_mut(local_index).unwrap(); - let processed: CompiledFunctionFrameInfo = match func { - SerializableFunctionFrameInfo::Processed(_) => { - // This should be a no-op on processed info - return; - } - SerializableFunctionFrameInfo::Unprocessed(unprocessed) => unprocessed.deserialize(), - }; - *func = SerializableFunctionFrameInfo::Processed(processed) - } - - fn processed_function_frame_info( - &self, - local_index: LocalFunctionIndex, - ) -> &CompiledFunctionFrameInfo { - match self.function_debug_info(local_index) { - SerializableFunctionFrameInfo::Processed(di) => &di, - _ => unreachable!("frame info should already be processed"), - } - } - /// Gets a function given a pc fn function_info(&self, pc: usize) -> Option<&FunctionInfo> { let (end, func) = self.functions.range(pc..).next()?; @@ -118,9 +92,7 @@ impl GlobalFrameInfo { // machine instruction that corresponds to `pc`, which then allows us to // map that to a wasm original source location. let rel_pos = pc - func.start; - let instr_map = &module - .processed_function_frame_info(func.local_index) - .address_map; + let instr_map = &module.function_debug_info(func.local_index).address_map; let pos = match instr_map .instructions .binary_search_by_key(&rel_pos, |map| map.code_offset) @@ -171,30 +143,13 @@ impl GlobalFrameInfo { pub fn lookup_trap_info(&self, pc: usize) -> Option<&TrapInformation> { let module = self.module_info(pc)?; let func = module.function_info(pc)?; - let traps = &module.processed_function_frame_info(func.local_index).traps; + let traps = &module.function_debug_info(func.local_index).traps; let idx = traps .binary_search_by_key(&((pc - func.start) as u32), |info| info.code_offset) .ok()?; Some(&traps[idx]) } - /// Should process the frame before anything? - pub fn should_process_frame(&self, pc: usize) -> Option { - let module = self.module_info(pc)?; - let func = module.function_info(pc)?; - let extra_func_info = module.function_debug_info(func.local_index); - Some(extra_func_info.is_unprocessed()) - } - - /// Process the frame info in case is not yet processed - pub fn maybe_process_frame(&mut self, pc: usize) -> Option<()> { - let module = self.module_info_mut(pc)?; - let func = module.function_info(pc)?; - let func_local_index = func.local_index; - module.process_function_debug_info(func_local_index); - Some(()) - } - /// Gets a module given a pc fn module_info(&self, pc: usize) -> Option<&ModuleInfoFrameInfo> { let (end, module_info) = self.ranges.range(pc..).next()?; @@ -203,15 +158,6 @@ impl GlobalFrameInfo { } Some(module_info) } - - /// Gets a module given a pc - fn module_info_mut(&mut self, pc: usize) -> Option<&mut ModuleInfoFrameInfo> { - let (end, module_info) = self.ranges.range_mut(pc..).next()?; - if pc < module_info.start || *end < pc { - return None; - } - Some(module_info) - } } impl Drop for GlobalFrameInfoRegistration { @@ -243,7 +189,7 @@ pub struct FunctionExtent { pub fn register( module: Arc, finished_functions: &BoxedSlice, - frame_infos: PrimaryMap, + frame_infos: PrimaryMap, ) -> Option { let mut min = usize::max_value(); let mut max = 0; diff --git a/lib/types/Cargo.toml b/lib/types/Cargo.toml index 3c8b0b8b5ed..7cb2901a633 100644 --- a/lib/types/Cargo.toml +++ b/lib/types/Cargo.toml @@ -14,7 +14,7 @@ edition = "2018" serde = { version = "1.0", features = ["derive"], optional = true, default-features = false } thiserror = "1.0" indexmap = { version = "1.4", features = ["serde-1"] } -rkyv = { version = "0.6", optional = true } +rkyv = { version = "0.6.1", optional = true } loupe = "0.1" [features] diff --git a/lib/types/src/archives.rs b/lib/types/src/archives.rs index 56f5aa5c9de..0a7d84a58ee 100644 --- a/lib/types/src/archives.rs +++ b/lib/types/src/archives.rs @@ -1,65 +1,9 @@ -use crate::entity::{EntityRef, PrimaryMap}; -use indexmap::IndexMap; - -use rkyv::{ - ser::Serializer, - std_impl::{ArchivedVec, VecResolver}, - Archive, Archived, Deserialize, DeserializeUnsized, Fallible, MetadataResolver, Serialize, -}; - #[cfg(feature = "core")] -use core::{hash::Hash, marker::PhantomData}; - +use core::hash::Hash; +use indexmap::IndexMap; +use rkyv::{Archive, Deserialize, Serialize}; #[cfg(feature = "std")] -use std::{collections::HashMap, hash::Hash, marker::PhantomData, mem::MaybeUninit}; - -/// PrimaryMap after archive -pub struct ArchivedPrimaryMap(ArchivedVec, PhantomData); - -impl Archive for PrimaryMap -where - K::Archived: EntityRef, -{ - type Archived = ArchivedPrimaryMap; - type Resolver = VecResolver>; - - fn resolve(&self, pos: usize, resolver: Self::Resolver, out: &mut MaybeUninit) { - let mut vec = MaybeUninit::uninit(); - Vec::resolve(&self.elems, pos, resolver, &mut vec); - // This is correct because the `resolve` method can never fail [citation needed] - let vec = unsafe { vec.assume_init() }; - let archived_primary_map = ArchivedPrimaryMap(vec, PhantomData); - unsafe { - out.as_mut_ptr().write(archived_primary_map); - } - } -} - -impl + EntityRef, V: Serialize, S: Serializer + ?Sized> Serialize - for PrimaryMap -where - K::Archived: EntityRef, -{ - fn serialize(&self, serializer: &mut S) -> Result { - self.elems.serialize(serializer) - } -} - -impl Deserialize, D> - for Archived> -where - K::Archived: Deserialize + EntityRef, - V::Archived: Deserialize, - [V::Archived]: DeserializeUnsized<[V], D>, -{ - fn deserialize(&self, deserializer: &mut D) -> Result, D::Error> { - let elems: Vec<_> = self.0.deserialize(deserializer)?; - Ok(PrimaryMap { - elems, - unused: PhantomData, - }) - } -} +use std::{collections::HashMap, hash::Hash}; #[derive(Serialize, Deserialize, Archive)] /// Rkyv Archivable IndexMap diff --git a/lib/types/src/entity/primary_map.rs b/lib/types/src/entity/primary_map.rs index a5827cad643..330db9e3f7c 100644 --- a/lib/types/src/entity/primary_map.rs +++ b/lib/types/src/entity/primary_map.rs @@ -13,6 +13,8 @@ use crate::lib::std::ops::{Index, IndexMut}; use crate::lib::std::slice; use crate::lib::std::vec::Vec; use loupe::{MemoryUsage, MemoryUsageTracker}; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use std::mem; @@ -34,6 +36,10 @@ use std::mem; /// `into_boxed_slice`. #[derive(Debug, Clone, Hash, PartialEq, Eq)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] pub struct PrimaryMap where K: EntityRef, diff --git a/lib/types/src/entity/secondary_map.rs b/lib/types/src/entity/secondary_map.rs index ac19c432fb7..afd84b54133 100644 --- a/lib/types/src/entity/secondary_map.rs +++ b/lib/types/src/entity/secondary_map.rs @@ -12,6 +12,8 @@ use crate::lib::std::ops::{Index, IndexMut}; use crate::lib::std::slice; use crate::lib::std::vec::Vec; use loupe::{MemoryUsage, MemoryUsageTracker}; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; #[cfg(feature = "enable-serde")] use serde::{ de::{Deserializer, SeqAccess, Visitor}, @@ -29,14 +31,18 @@ use std::mem; /// The map does not track if an entry for a key has been inserted or not. Instead it behaves as if /// all keys have a default entry from the beginning. #[derive(Debug, Clone)] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] pub struct SecondaryMap where K: EntityRef, V: Clone, { - elems: Vec, - default: V, - unused: PhantomData, + pub(crate) elems: Vec, + pub(crate) default: V, + pub(crate) unused: PhantomData, } /// Shared `SecondaryMap` implementation for all value types. diff --git a/lib/types/src/lib.rs b/lib/types/src/lib.rs index 6cd30d2a9c6..a471abecc08 100644 --- a/lib/types/src/lib.rs +++ b/lib/types/src/lib.rs @@ -90,7 +90,7 @@ pub use types::{ }; #[cfg(feature = "enable-rkyv")] -pub use archives::{ArchivableIndexMap, ArchivedPrimaryMap}; +pub use archives::ArchivableIndexMap; /// Version number of this crate. pub const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/lib/vm/Cargo.toml b/lib/vm/Cargo.toml index f51babb256a..c4e1044bb11 100644 --- a/lib/vm/Cargo.toml +++ b/lib/vm/Cargo.toml @@ -21,7 +21,7 @@ more-asserts = "0.2" cfg-if = "0.1" backtrace = "0.3" serde = { version = "1.0", features = ["derive", "rc"] } -rkyv = { version = "0.6", optional = true} +rkyv = { version = "0.6.1", optional = true} loupe = { version = "0.1", features = ["enable-indexmap"] } [target.'cfg(target_os = "windows")'.dependencies] diff --git a/lib/vm/src/lib.rs b/lib/vm/src/lib.rs index a7f099385e8..dc4a1d8f2fb 100644 --- a/lib/vm/src/lib.rs +++ b/lib/vm/src/lib.rs @@ -1,6 +1,7 @@ //! Runtime library support for Wasmer. #![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)] +#![deny(trivial_numeric_casts, unused_extern_crates)] #![warn(unused_import_braces)] #![cfg_attr( feature = "cargo-clippy", diff --git a/lib/vm/src/libcalls.rs b/lib/vm/src/libcalls.rs index f03fc244719..1d74e9abc9c 100644 --- a/lib/vm/src/libcalls.rs +++ b/lib/vm/src/libcalls.rs @@ -35,6 +35,8 @@ //! } //! ``` +#![allow(missing_docs)] // For some reason lint fails saying that `LibCall` is not documented, when it actually is + use crate::func_data_registry::VMFuncRef; use crate::probestack::PROBESTACK; use crate::table::{RawTableElement, TableElement}; @@ -42,6 +44,8 @@ use crate::trap::{raise_lib_trap, Trap, TrapCode}; use crate::vmcontext::VMContext; use crate::VMExternRef; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use serde::{Deserialize, Serialize}; use std::fmt; use wasmer_types::{ @@ -680,6 +684,10 @@ pub static wasmer_vm_probestack: unsafe extern "C" fn() = PROBESTACK; /// The name of a runtime library routine. /// /// This list is likely to grow over time. +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, MemoryUsage)] pub enum LibCall { /// ceil.f32 diff --git a/lib/vm/src/trap/trapcode.rs b/lib/vm/src/trap/trapcode.rs index ee3e910fb1b..e262a30cf88 100644 --- a/lib/vm/src/trap/trapcode.rs +++ b/lib/vm/src/trap/trapcode.rs @@ -6,6 +6,8 @@ use core::fmt::{self, Display, Formatter}; use core::str::FromStr; use loupe::MemoryUsage; +#[cfg(feature = "enable-rkyv")] +use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -13,6 +15,10 @@ use thiserror::Error; /// /// All trap instructions have an explicit trap code. #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize, Error, MemoryUsage)] +#[cfg_attr( + feature = "enable-rkyv", + derive(RkyvSerialize, RkyvDeserialize, Archive) +)] #[repr(u32)] pub enum TrapCode { /// The current stack space was exhausted.