mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 13:18:20 +00:00
Got half-baked engine
This commit is contained in:
30
Cargo.lock
generated
30
Cargo.lock
generated
@@ -353,6 +353,12 @@ dependencies = [
|
|||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "downcast-rs"
|
||||||
|
version = "1.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.5.3"
|
version = "1.5.3"
|
||||||
@@ -1465,6 +1471,7 @@ dependencies = [
|
|||||||
"wasmer-compiler-cranelift",
|
"wasmer-compiler-cranelift",
|
||||||
"wasmer-compiler-llvm",
|
"wasmer-compiler-llvm",
|
||||||
"wasmer-compiler-singlepass",
|
"wasmer-compiler-singlepass",
|
||||||
|
"wasmer-engine",
|
||||||
"wasmer-jit",
|
"wasmer-jit",
|
||||||
"wasmer-runtime",
|
"wasmer-runtime",
|
||||||
"wat",
|
"wat",
|
||||||
@@ -1488,6 +1495,7 @@ dependencies = [
|
|||||||
"wasmer-compiler-cranelift",
|
"wasmer-compiler-cranelift",
|
||||||
"wasmer-compiler-llvm",
|
"wasmer-compiler-llvm",
|
||||||
"wasmer-compiler-singlepass",
|
"wasmer-compiler-singlepass",
|
||||||
|
"wasmer-engine",
|
||||||
"wasmer-jit",
|
"wasmer-jit",
|
||||||
"wasmer-wasi",
|
"wasmer-wasi",
|
||||||
"wasmer-wasi-experimental-io-devices",
|
"wasmer-wasi-experimental-io-devices",
|
||||||
@@ -1574,6 +1582,27 @@ dependencies = [
|
|||||||
"wasmer-runtime",
|
"wasmer-runtime",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasmer-engine"
|
||||||
|
version = "0.16.2"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"bincode",
|
||||||
|
"downcast-rs",
|
||||||
|
"lazy_static",
|
||||||
|
"more-asserts",
|
||||||
|
"region",
|
||||||
|
"rustc-demangle",
|
||||||
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
|
"target-lexicon",
|
||||||
|
"thiserror",
|
||||||
|
"wasm-common",
|
||||||
|
"wasmer-compiler",
|
||||||
|
"wasmer-runtime",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmer-jit"
|
name = "wasmer-jit"
|
||||||
version = "0.16.2"
|
version = "0.16.2"
|
||||||
@@ -1590,6 +1619,7 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"wasm-common",
|
"wasm-common",
|
||||||
"wasmer-compiler",
|
"wasmer-compiler",
|
||||||
|
"wasmer-engine",
|
||||||
"wasmer-runtime",
|
"wasmer-runtime",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ wasmer-compiler = { path = "lib/compiler" }
|
|||||||
wasmer-compiler-cranelift = { path = "lib/compiler-cranelift", optional = true }
|
wasmer-compiler-cranelift = { path = "lib/compiler-cranelift", optional = true }
|
||||||
wasmer-compiler-singlepass = { path = "lib/compiler-singlepass", optional = true }
|
wasmer-compiler-singlepass = { path = "lib/compiler-singlepass", optional = true }
|
||||||
wasmer-compiler-llvm = { path = "lib/compiler-llvm", optional = true }
|
wasmer-compiler-llvm = { path = "lib/compiler-llvm", optional = true }
|
||||||
|
wasmer-engine = { path = "lib/engine" }
|
||||||
wasmer-jit = { path = "lib/jit" }
|
wasmer-jit = { path = "lib/jit" }
|
||||||
wasmer-wasi = { path = "lib/wasi", optional = true }
|
wasmer-wasi = { path = "lib/wasi", optional = true }
|
||||||
wasmer-wasi-experimental-io-devices = { path = "lib/wasi-experimental-io-devices", optional = true }
|
wasmer-wasi-experimental-io-devices = { path = "lib/wasi-experimental-io-devices", optional = true }
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ wasmer-compiler-singlepass = { path = "../compiler-singlepass", version = "0.16.
|
|||||||
wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "0.16.2", optional = true }
|
wasmer-compiler-cranelift = { path = "../compiler-cranelift", version = "0.16.2", optional = true }
|
||||||
wasmer-compiler-llvm = { path = "../compiler-llvm", version = "0.16.2", optional = true }
|
wasmer-compiler-llvm = { path = "../compiler-llvm", version = "0.16.2", optional = true }
|
||||||
wasmer-compiler = { path = "../compiler", version = "0.16.2" }
|
wasmer-compiler = { path = "../compiler", version = "0.16.2" }
|
||||||
|
wasmer-engine = { path = "../engine", version = "0.16.2" }
|
||||||
wasmer-jit = { path = "../jit", version = "0.16.2" }
|
wasmer-jit = { path = "../jit", version = "0.16.2" }
|
||||||
wasm-common = { path = "../wasm-common", version = "0.16.2" }
|
wasm-common = { path = "../wasm-common", version = "0.16.2" }
|
||||||
indexmap = { version = "1.3.2", features = ["serde-1"] }
|
indexmap = { version = "1.3.2", features = ["serde-1"] }
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::{
|
|||||||
ffi::c_void,
|
ffi::c_void,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
};
|
};
|
||||||
use wasmer_jit::Resolver;
|
use wasmer_engine::Resolver;
|
||||||
use wasmer_runtime::Export;
|
use wasmer_runtime::Export;
|
||||||
|
|
||||||
/// The `LikeNamespace` trait represents objects that act as a namespace for imports.
|
/// The `LikeNamespace` trait represents objects that act as a namespace for imports.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::externals::Extern;
|
|||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
use crate::store::Store;
|
use crate::store::Store;
|
||||||
use crate::InstantiationError;
|
use crate::InstantiationError;
|
||||||
use wasmer_jit::Resolver;
|
use wasmer_engine::Resolver;
|
||||||
use wasmer_runtime::InstanceHandle;
|
use wasmer_runtime::InstanceHandle;
|
||||||
|
|
||||||
/// A WebAssembly Instance is a stateful, executable
|
/// A WebAssembly Instance is a stateful, executable
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ pub use crate::types::{
|
|||||||
|
|
||||||
pub use wasm_common::{ValueType, WasmExternType, WasmTypeList};
|
pub use wasm_common::{ValueType, WasmExternType, WasmTypeList};
|
||||||
pub use wasmer_compiler::{CompilerConfig, Features, Target};
|
pub use wasmer_compiler::{CompilerConfig, Features, Target};
|
||||||
pub use wasmer_jit::{
|
pub use wasmer_engine::{
|
||||||
DeserializeError, InstantiationError, LinkError, RuntimeError, SerializeError,
|
DeserializeError, InstantiationError, LinkError, RuntimeError, SerializeError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use std::path::Path;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use wasmer_compiler::{CompileError, WasmError};
|
use wasmer_compiler::{CompileError, WasmError};
|
||||||
use wasmer_jit::{CompiledModule, DeserializeError, Resolver, SerializeError};
|
use wasmer_engine::{CompiledModule, DeserializeError, Resolver, SerializeError};
|
||||||
use wasmer_runtime::InstanceHandle;
|
use wasmer_runtime::InstanceHandle;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
@@ -30,7 +30,7 @@ pub enum IoCompileError {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Module {
|
pub struct Module {
|
||||||
store: Store,
|
store: Store,
|
||||||
compiled: Arc<CompiledModule>,
|
compiled: Arc<dyn CompiledModule>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
@@ -173,10 +173,11 @@ impl Module {
|
|||||||
Ok(Self::from_compiled_module(store, compiled))
|
Ok(Self::from_compiled_module(store, compiled))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_compiled_module(store: &Store, compiled: CompiledModule) -> Self {
|
fn from_compiled_module(store: &Store, compiled: Arc<CompiledModule>) -> Self
|
||||||
|
{
|
||||||
Module {
|
Module {
|
||||||
store: store.clone(),
|
store: store.clone(),
|
||||||
compiled: Arc::new(compiled),
|
compiled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use target_lexicon::{OperatingSystem, PointerWidth, Triple, HOST};
|
|||||||
use wasm_common::{MemoryType, Pages, TableType};
|
use wasm_common::{MemoryType, Pages, TableType};
|
||||||
use wasmer_runtime::{LinearMemory, Table};
|
use wasmer_runtime::{LinearMemory, Table};
|
||||||
use wasmer_runtime::{MemoryPlan, MemoryStyle, TablePlan, TableStyle};
|
use wasmer_runtime::{MemoryPlan, MemoryStyle, TablePlan, TableStyle};
|
||||||
|
use wasmer_engine::Tunables as BaseTunables;
|
||||||
|
|
||||||
/// Tunable parameters for WebAssembly compilation.
|
/// Tunable parameters for WebAssembly compilation.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -57,7 +58,7 @@ impl Tunables {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl wasmer_jit::Tunables for Tunables {
|
impl BaseTunables for Tunables {
|
||||||
/// Get a `MemoryPlan` for the provided `MemoryType`
|
/// Get a `MemoryPlan` for the provided `MemoryType`
|
||||||
fn memory_plan(&self, memory: MemoryType) -> MemoryPlan {
|
fn memory_plan(&self, memory: MemoryType) -> MemoryPlan {
|
||||||
// A heap with a maximum that doesn't exceed the static memory bound specified by the
|
// A heap with a maximum that doesn't exceed the static memory bound specified by the
|
||||||
|
|||||||
34
lib/engine/Cargo.toml
Normal file
34
lib/engine/Cargo.toml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasmer-engine"
|
||||||
|
version = "0.16.2"
|
||||||
|
authors = ["Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||||
|
description = "Wasmer Engine abstraction"
|
||||||
|
license = "(Apache-2.0 WITH LLVM-exception) or MIT"
|
||||||
|
categories = ["wasm"]
|
||||||
|
keywords = ["webassembly", "wasm"]
|
||||||
|
repository = "https://github.com/wasmerio/wasmer"
|
||||||
|
readme = "README.md"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasm-common = { path = "../wasm-common", version = "0.16.2" }
|
||||||
|
wasmer-compiler = { path = "../compiler", version = "0.16.2", default-features = false }
|
||||||
|
wasmer-runtime = { path = "../runtime", version = "0.16.2" }
|
||||||
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
|
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
|
||||||
|
backtrace = "0.3.46"
|
||||||
|
rustc-demangle = "0.1.16"
|
||||||
|
more-asserts = "0.2.1"
|
||||||
|
thiserror = "1.0.16"
|
||||||
|
region = "2.1.2"
|
||||||
|
serde = { version = "1.0.106", sfeatures = ["derive", "rc"] }
|
||||||
|
serde_bytes = { version = "0.11.3" }
|
||||||
|
bincode = "1.2.1"
|
||||||
|
lazy_static = "1.4"
|
||||||
|
downcast-rs = "1.1.1"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
winapi = { version = "0.3.8", features = ["winnt", "impl-default"] }
|
||||||
|
|
||||||
|
[badges]
|
||||||
|
maintenance = { status = "actively-developed" }
|
||||||
12
lib/engine/README.md
Normal file
12
lib/engine/README.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Wasmer Engine
|
||||||
|
|
||||||
|
The Wasmer Engine is the general abstraction for Engines in Wasmer.
|
||||||
|
It currently has two implementations:
|
||||||
|
* Wasmer JIT
|
||||||
|
* Wasmer Native
|
||||||
|
|
||||||
|
### Acknowledgments
|
||||||
|
|
||||||
|
This project borrowed some of the code of the trap implementation from the [wasmtime-api](https://crates.io/crates/wasmtime), the code since then has evolved significantly.
|
||||||
|
|
||||||
|
Please check [Wasmer ATTRIBUTIONS](https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md) to further see licenses and other attributions of the project.
|
||||||
49
lib/engine/src/engine.rs
Normal file
49
lib/engine/src/engine.rs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
//! JIT compilation.
|
||||||
|
|
||||||
|
use crate::error::InstantiationError;
|
||||||
|
use crate::resolver::Resolver;
|
||||||
|
use crate::tunables::Tunables;
|
||||||
|
use crate::{CompiledModule, DeserializeError, SerializeError};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use wasm_common::FuncType;
|
||||||
|
use wasmer_compiler::CompileError;
|
||||||
|
use wasmer_runtime::{InstanceHandle, VMSharedSignatureIndex, VMTrampoline};
|
||||||
|
|
||||||
|
/// A unimplemented Wasmer `Engine`.
|
||||||
|
/// This trait is used by implementors to implement custom engines,
|
||||||
|
/// such as: JIT or Native.
|
||||||
|
pub trait Engine {
|
||||||
|
/// The `CompiledModule` type
|
||||||
|
type Product: CompiledModule;
|
||||||
|
|
||||||
|
/// Get the tunables
|
||||||
|
fn tunables(&self) -> &Tunables;
|
||||||
|
|
||||||
|
/// Register a signature
|
||||||
|
fn register_signature(&self, func_type: &FuncType) -> VMSharedSignatureIndex;
|
||||||
|
|
||||||
|
/// Lookup a signature
|
||||||
|
fn lookup_signature(&self, sig: VMSharedSignatureIndex) -> Option<FuncType>;
|
||||||
|
|
||||||
|
/// Retrieves a trampoline given a signature
|
||||||
|
fn trampoline(&self, sig: VMSharedSignatureIndex) -> Option<VMTrampoline>;
|
||||||
|
|
||||||
|
/// Validates a WebAssembly module
|
||||||
|
fn validate(&self, binary: &[u8]) -> Result<(), CompileError>;
|
||||||
|
|
||||||
|
/// Compile a WebAssembly binary
|
||||||
|
fn compile(&self, binary: &[u8]) -> Result<Self::Product, CompileError>;
|
||||||
|
|
||||||
|
/// Instantiates a WebAssembly module
|
||||||
|
fn instantiate(
|
||||||
|
&self,
|
||||||
|
compiled_module: &Arc<Self::Product>,
|
||||||
|
resolver: &dyn Resolver,
|
||||||
|
) -> Result<InstanceHandle, InstantiationError>;
|
||||||
|
|
||||||
|
/// Serializes a WebAssembly module
|
||||||
|
fn serialize(&self, compiled_module: &Arc<Self::Product>) -> Result<Vec<u8>, SerializeError>;
|
||||||
|
|
||||||
|
/// Deserializes a WebAssembly module
|
||||||
|
fn deserialize(&self, bytes: &[u8]) -> Result<Self::Product, DeserializeError>;
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// TODO: Move this errors into a common engine crate.
|
|
||||||
//! The WebAssembly possible errors
|
//! The WebAssembly possible errors
|
||||||
use crate::trap::RuntimeError;
|
use crate::trap::RuntimeError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
45
lib/engine/src/lib.rs
Normal file
45
lib/engine/src/lib.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
//! Generic Engine abstraction for Wasmer Engines.
|
||||||
|
|
||||||
|
#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
|
||||||
|
#![warn(unused_import_braces)]
|
||||||
|
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
|
||||||
|
#![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 engine;
|
||||||
|
mod error;
|
||||||
|
mod module;
|
||||||
|
mod resolver;
|
||||||
|
mod serialize;
|
||||||
|
mod trap;
|
||||||
|
mod tunables;
|
||||||
|
|
||||||
|
pub use crate::engine::Engine;
|
||||||
|
pub use crate::error::{
|
||||||
|
DeserializeError, ImportError, InstantiationError, LinkError, SerializeError,
|
||||||
|
};
|
||||||
|
pub use crate::module::CompiledModule;
|
||||||
|
pub use crate::resolver::{resolve_imports, NullResolver, Resolver};
|
||||||
|
pub use crate::trap::*;
|
||||||
|
pub use crate::tunables::Tunables;
|
||||||
|
pub use crate::serialize::SerializableFunctionFrameInfo;
|
||||||
|
|
||||||
|
pub use wasmer_compiler::CompilerConfig;
|
||||||
|
|
||||||
|
/// Version number of this crate.
|
||||||
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
19
lib/engine/src/module.rs
Normal file
19
lib/engine/src/module.rs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use wasmer_runtime::Module;
|
||||||
|
|
||||||
|
use downcast_rs::{DowncastSync, impl_downcast};
|
||||||
|
|
||||||
|
/// The `CompiledModule` trait is used by engine implementors, such
|
||||||
|
/// as a JIT or Native execution.
|
||||||
|
pub trait CompiledModule: DowncastSync {
|
||||||
|
/// Return a reference-counting pointer to a module.
|
||||||
|
fn module(&self) -> &Arc<Module>;
|
||||||
|
|
||||||
|
/// Return a reference-counting pointer to a module.
|
||||||
|
fn module_mut(&mut self) -> &mut Arc<Module>;
|
||||||
|
|
||||||
|
/// Return a reference to a module.
|
||||||
|
fn module_ref(&self) -> &Module;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_downcast!(sync CompiledModule); // `sync` => also produce `Arc` downcasts.
|
||||||
107
lib/engine/src/serialize.rs
Normal file
107
lib/engine/src/serialize.rs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
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)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct UnprocessedFunctionFrameInfo {
|
||||||
|
#[serde(with = "serde_bytes")]
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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)]
|
||||||
|
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 {
|
||||||
|
match self {
|
||||||
|
Self::Unprocessed(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Below:
|
||||||
|
// The custom ser/de for `SerializableFunctionFrameInfo`.
|
||||||
|
|
||||||
|
impl Serialize for SerializableFunctionFrameInfo {
|
||||||
|
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
||||||
|
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<E>(self, v: Vec<u8>) -> Result<Self::Value, E> {
|
||||||
|
Ok(UnprocessedFunctionFrameInfo { bytes: v })
|
||||||
|
}
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> {
|
||||||
|
Ok(UnprocessedFunctionFrameInfo { bytes: v.to_vec() })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for SerializableFunctionFrameInfo {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
Ok(SerializableFunctionFrameInfo::Unprocessed(
|
||||||
|
deserializer.deserialize_byte_buf(FunctionFrameInfoVisitor)?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
4
lib/engine/src/trap/mod.rs
Normal file
4
lib/engine/src/trap/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
mod error;
|
||||||
|
mod frame_info;
|
||||||
|
pub use error::RuntimeError;
|
||||||
|
pub use frame_info::{register as register_frame_info, FrameInfo, GlobalFrameInfoRegistration, FRAME_INFO};
|
||||||
@@ -14,6 +14,7 @@ edition = "2018"
|
|||||||
wasm-common = { path = "../wasm-common", version = "0.16.2" }
|
wasm-common = { path = "../wasm-common", version = "0.16.2" }
|
||||||
wasmer-compiler = { path = "../compiler", version = "0.16.2", default-features = false }
|
wasmer-compiler = { path = "../compiler", version = "0.16.2", default-features = false }
|
||||||
wasmer-runtime = { path = "../runtime", version = "0.16.2" }
|
wasmer-runtime = { path = "../runtime", version = "0.16.2" }
|
||||||
|
wasmer-engine = { path = "../engine", version = "0.16.2" }
|
||||||
target-lexicon = { version = "0.10.0", default-features = false }
|
target-lexicon = { version = "0.10.0", default-features = false }
|
||||||
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
|
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
|
||||||
backtrace = "0.3.46"
|
backtrace = "0.3.46"
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
//! JIT compilation.
|
//! JIT compilation.
|
||||||
|
|
||||||
use crate::error::InstantiationError;
|
use wasmer_engine::{Engine, InstantiationError, Resolver, Tunables, DeserializeError, SerializeError, CompiledModule as BaseCompiledModule};
|
||||||
use crate::resolver::Resolver;
|
use crate::{CodeMemory, CompiledModule};
|
||||||
use crate::tunables::Tunables;
|
|
||||||
use crate::CodeMemory;
|
|
||||||
use crate::{CompiledModule, DeserializeError, SerializeError};
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -12,7 +9,7 @@ use wasm_common::entity::PrimaryMap;
|
|||||||
use wasm_common::{FuncType, LocalFuncIndex, MemoryIndex, TableIndex};
|
use wasm_common::{FuncType, LocalFuncIndex, MemoryIndex, TableIndex};
|
||||||
use wasmer_compiler::{
|
use wasmer_compiler::{
|
||||||
Compilation, CompileError, Compiler as BaseCompiler, CompilerConfig, FunctionBody,
|
Compilation, CompileError, Compiler as BaseCompiler, CompilerConfig, FunctionBody,
|
||||||
FunctionBodyData, ModuleTranslationState, Target,
|
FunctionBodyData, ModuleTranslationState,
|
||||||
};
|
};
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
InstanceHandle, MemoryPlan, Module, SignatureRegistry, TablePlan, VMFunctionBody,
|
InstanceHandle, MemoryPlan, Module, SignatureRegistry, TablePlan, VMFunctionBody,
|
||||||
@@ -44,11 +41,6 @@ impl JITEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the tunables
|
|
||||||
pub fn tunables(&self) -> &dyn Tunables {
|
|
||||||
&**self.tunables
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn compiler(&self) -> std::cell::Ref<'_, JITEngineInner> {
|
pub(crate) fn compiler(&self) -> std::cell::Ref<'_, JITEngineInner> {
|
||||||
self.inner.borrow()
|
self.inner.borrow()
|
||||||
}
|
}
|
||||||
@@ -57,6 +49,13 @@ impl JITEngine {
|
|||||||
self.inner.borrow_mut()
|
self.inner.borrow_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get the tunables
|
||||||
|
pub fn tunables(&self) -> &dyn Tunables {
|
||||||
|
&**self.tunables
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
// impl Engine for JITEngine {
|
||||||
/// Register a signature
|
/// Register a signature
|
||||||
pub fn register_signature(&self, func_type: &FuncType) -> VMSharedSignatureIndex {
|
pub fn register_signature(&self, func_type: &FuncType) -> VMSharedSignatureIndex {
|
||||||
let compiler = self.compiler();
|
let compiler = self.compiler();
|
||||||
@@ -80,27 +79,30 @@ impl JITEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a WebAssembly binary
|
/// Compile a WebAssembly binary
|
||||||
pub fn compile(&self, binary: &[u8]) -> Result<CompiledModule, CompileError> {
|
pub fn compile(&self, binary: &[u8]) -> Result<Arc<dyn BaseCompiledModule>, CompileError> {
|
||||||
CompiledModule::new(&self, binary)
|
Ok(Arc::new(CompiledModule::new(&self, binary)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiates a WebAssembly module
|
/// Instantiates a WebAssembly module
|
||||||
pub fn instantiate(
|
pub fn instantiate(
|
||||||
&self,
|
&self,
|
||||||
compiled_module: &CompiledModule,
|
compiled_module: &Arc<dyn BaseCompiledModule>,
|
||||||
resolver: &dyn Resolver,
|
resolver: &dyn Resolver,
|
||||||
) -> Result<InstanceHandle, InstantiationError> {
|
) -> Result<InstanceHandle, InstantiationError>
|
||||||
|
{
|
||||||
|
let compiled_module = compiled_module.downcast_ref::<CompiledModule>().unwrap();
|
||||||
unsafe { compiled_module.instantiate(&self, resolver, Box::new(())) }
|
unsafe { compiled_module.instantiate(&self, resolver, Box::new(())) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes a WebAssembly module
|
/// Serializes a WebAssembly module
|
||||||
pub fn serialize(&self, compiled_module: &CompiledModule) -> Result<Vec<u8>, SerializeError> {
|
pub fn serialize(&self, compiled_module: &Arc<dyn BaseCompiledModule>) -> Result<Vec<u8>, SerializeError> {
|
||||||
|
let compiled_module = compiled_module.downcast_ref::<CompiledModule>().unwrap();
|
||||||
compiled_module.serialize()
|
compiled_module.serialize()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes a WebAssembly module
|
/// Deserializes a WebAssembly module
|
||||||
pub fn deserialize(&self, bytes: &[u8]) -> Result<CompiledModule, DeserializeError> {
|
pub fn deserialize(&self, bytes: &[u8]) -> Result<Arc<dyn BaseCompiledModule>, DeserializeError> {
|
||||||
CompiledModule::deserialize(&self, bytes)
|
Ok(Arc::new(CompiledModule::deserialize(&self, bytes)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,28 +27,16 @@
|
|||||||
|
|
||||||
mod code_memory;
|
mod code_memory;
|
||||||
mod engine;
|
mod engine;
|
||||||
mod error;
|
|
||||||
mod function_table;
|
mod function_table;
|
||||||
mod link;
|
mod link;
|
||||||
mod module;
|
mod module;
|
||||||
mod resolver;
|
|
||||||
mod serialize;
|
mod serialize;
|
||||||
mod trap;
|
|
||||||
mod tunables;
|
|
||||||
|
|
||||||
pub use crate::code_memory::CodeMemory;
|
pub use crate::code_memory::CodeMemory;
|
||||||
pub use crate::engine::JITEngine;
|
pub use crate::engine::JITEngine;
|
||||||
pub use crate::error::{
|
|
||||||
DeserializeError, ImportError, InstantiationError, LinkError, SerializeError,
|
|
||||||
};
|
|
||||||
pub use crate::function_table::FunctionTable;
|
pub use crate::function_table::FunctionTable;
|
||||||
pub use crate::link::link_module;
|
pub use crate::link::link_module;
|
||||||
pub use crate::module::CompiledModule;
|
pub use crate::module::CompiledModule;
|
||||||
pub use crate::resolver::{resolve_imports, NullResolver, Resolver};
|
|
||||||
pub use crate::trap::*;
|
|
||||||
pub use crate::tunables::Tunables;
|
|
||||||
|
|
||||||
pub use wasmer_compiler::CompilerConfig;
|
|
||||||
|
|
||||||
/// 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");
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ use wasmer_compiler::{JumpTable, JumpTableOffsets, RelocationKind, RelocationTar
|
|||||||
use wasmer_runtime::Module;
|
use wasmer_runtime::Module;
|
||||||
use wasmer_runtime::VMFunctionBody;
|
use wasmer_runtime::VMFunctionBody;
|
||||||
|
|
||||||
/// Links a module that has been compiled with `compiled_module` in `wasmer-compiler::Compiler`.
|
/// Links a module, patching the allocated functions with the
|
||||||
///
|
/// requiredd relocations and jump tables.
|
||||||
/// Performs all required relocations inside the function code, provided the necessary metadata.
|
|
||||||
pub fn link_module(
|
pub fn link_module(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
allocated_functions: &PrimaryMap<LocalFuncIndex, *mut [VMFunctionBody]>,
|
allocated_functions: &PrimaryMap<LocalFuncIndex, *mut [VMFunctionBody]>,
|
||||||
@@ -68,10 +67,8 @@ pub fn link_module(
|
|||||||
.wrapping_add(reloc_addend as u32);
|
.wrapping_add(reloc_addend as u32);
|
||||||
write_unaligned(reloc_address as *mut u32, reloc_delta_u32);
|
write_unaligned(reloc_address as *mut u32, reloc_delta_u32);
|
||||||
}
|
}
|
||||||
RelocationKind::X86PCRelRodata4 => {
|
RelocationKind::X86PCRelRodata4 => {}
|
||||||
// ignore
|
_ => panic!("Relocation kind unsupported"),
|
||||||
}
|
|
||||||
_ => panic!("unsupported reloc kind"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,16 +4,14 @@
|
|||||||
//! steps.
|
//! steps.
|
||||||
|
|
||||||
use crate::engine::{JITEngine, JITEngineInner};
|
use crate::engine::{JITEngine, JITEngineInner};
|
||||||
use crate::error::{DeserializeError, SerializeError};
|
use wasmer_engine::{DeserializeError, SerializeError, InstantiationError, LinkError, SerializableFunctionFrameInfo,
|
||||||
use crate::error::{InstantiationError, LinkError};
|
resolve_imports, Resolver, register_frame_info, GlobalFrameInfoRegistration, RuntimeError,
|
||||||
use crate::link::link_module;
|
CompiledModule as BaseCompiledModule
|
||||||
use crate::resolver::{resolve_imports, Resolver};
|
};
|
||||||
use crate::serialize::{
|
use crate::link::link_module;
|
||||||
SerializableCompilation, SerializableFunctionFrameInfo, SerializableModule,
|
use crate::serialize::{
|
||||||
|
SerializableCompilation, SerializableModule,
|
||||||
};
|
};
|
||||||
use crate::trap::register as register_frame_info;
|
|
||||||
use crate::trap::GlobalFrameInfoRegistration;
|
|
||||||
use crate::trap::RuntimeError;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
@@ -168,15 +166,7 @@ impl CompiledModule {
|
|||||||
&self.serializable.table_plans
|
&self.serializable.table_plans
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Crate an `Instance` from this `CompiledModule`.
|
/// Instantiate the module
|
||||||
///
|
|
||||||
/// Note that if only one instance of this module is needed, it may be more
|
|
||||||
/// efficient to call the top-level `instantiate`, since that avoids copying
|
|
||||||
/// the data initializers.
|
|
||||||
///
|
|
||||||
/// # Unsafety
|
|
||||||
///
|
|
||||||
/// See `InstanceHandle::new`
|
|
||||||
pub unsafe fn instantiate(
|
pub unsafe fn instantiate(
|
||||||
&self,
|
&self,
|
||||||
jit: &JITEngine,
|
jit: &JITEngine,
|
||||||
@@ -227,21 +217,6 @@ impl CompiledModule {
|
|||||||
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))
|
.map_err(|trap| InstantiationError::Start(RuntimeError::from_trap(trap)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a reference-counting pointer to a module.
|
|
||||||
pub fn module(&self) -> &Arc<Module> {
|
|
||||||
&self.serializable.module
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference-counting pointer to a module.
|
|
||||||
pub fn module_mut(&mut self) -> &mut Arc<Module> {
|
|
||||||
&mut self.serializable.module
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return a reference to a module.
|
|
||||||
pub fn module_ref(&self) -> &Module {
|
|
||||||
&self.serializable.module
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Register this module's stack frame information into the global scope.
|
/// Register this module's stack frame information into the global scope.
|
||||||
///
|
///
|
||||||
/// This is required to ensure that any traps can be properly symbolicated.
|
/// This is required to ensure that any traps can be properly symbolicated.
|
||||||
@@ -259,6 +234,22 @@ impl CompiledModule {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
unsafe impl Sync for CompiledModule {}
|
||||||
|
unsafe impl Send for CompiledModule {}
|
||||||
|
|
||||||
|
impl BaseCompiledModule for CompiledModule {
|
||||||
|
fn module(&self) -> &Arc<Module> {
|
||||||
|
&self.serializable.module
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module_mut(&mut self) -> &mut Arc<Module> {
|
||||||
|
&mut self.serializable.module
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module_ref(&self) -> &Module {
|
||||||
|
&self.serializable.module
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Allocate memory for just the memories of the current module.
|
/// Allocate memory for just the memories of the current module.
|
||||||
fn create_memories(
|
fn create_memories(
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
use serde::de::{Deserializer, Visitor};
|
|
||||||
use serde::ser::Serializer;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_compiler::{CompiledFunctionFrameInfo, FunctionBody, JumpTableOffsets, Relocation};
|
use wasmer_compiler::{FunctionBody, JumpTableOffsets, Relocation};
|
||||||
use wasmer_runtime::Module;
|
use wasmer_runtime::Module;
|
||||||
|
use wasmer_engine::SerializableFunctionFrameInfo;
|
||||||
use wasm_common::entity::PrimaryMap;
|
use wasm_common::entity::PrimaryMap;
|
||||||
use wasm_common::{LocalFuncIndex, MemoryIndex, OwnedDataInitializer, TableIndex};
|
use wasm_common::{LocalFuncIndex, MemoryIndex, OwnedDataInitializer, TableIndex};
|
||||||
use wasmer_runtime::{MemoryPlan, TablePlan};
|
use wasmer_runtime::{MemoryPlan, TablePlan};
|
||||||
@@ -33,105 +30,3 @@ pub struct SerializableModule {
|
|||||||
pub memory_plans: PrimaryMap<MemoryIndex, MemoryPlan>,
|
pub memory_plans: PrimaryMap<MemoryIndex, MemoryPlan>,
|
||||||
pub table_plans: PrimaryMap<TableIndex, TablePlan>,
|
pub table_plans: PrimaryMap<TableIndex, TablePlan>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the unserialized verison of `CompiledFunctionFrameInfo`.
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
|
||||||
#[serde(transparent)]
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct UnprocessedFunctionFrameInfo {
|
|
||||||
#[serde(with = "serde_bytes")]
|
|
||||||
bytes: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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)]
|
|
||||||
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 {
|
|
||||||
match self {
|
|
||||||
Self::Unprocessed(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Below:
|
|
||||||
// The custom ser/de for `SerializableFunctionFrameInfo`.
|
|
||||||
|
|
||||||
impl Serialize for SerializableFunctionFrameInfo {
|
|
||||||
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
|
|
||||||
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<E>(self, v: Vec<u8>) -> Result<Self::Value, E> {
|
|
||||||
Ok(UnprocessedFunctionFrameInfo { bytes: v })
|
|
||||||
}
|
|
||||||
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> {
|
|
||||||
Ok(UnprocessedFunctionFrameInfo { bytes: v.to_vec() })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for SerializableFunctionFrameInfo {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: Deserializer<'de>,
|
|
||||||
{
|
|
||||||
Ok(SerializableFunctionFrameInfo::Unprocessed(
|
|
||||||
deserializer.deserialize_byte_buf(FunctionFrameInfoVisitor)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
mod error;
|
|
||||||
mod frame_info;
|
|
||||||
pub use error::RuntimeError;
|
|
||||||
pub use frame_info::{register, FrameInfo, GlobalFrameInfoRegistration, FRAME_INFO};
|
|
||||||
Reference in New Issue
Block a user