mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 05:08:19 +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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.5.3"
|
||||
@@ -1465,6 +1471,7 @@ dependencies = [
|
||||
"wasmer-compiler-cranelift",
|
||||
"wasmer-compiler-llvm",
|
||||
"wasmer-compiler-singlepass",
|
||||
"wasmer-engine",
|
||||
"wasmer-jit",
|
||||
"wasmer-runtime",
|
||||
"wat",
|
||||
@@ -1488,6 +1495,7 @@ dependencies = [
|
||||
"wasmer-compiler-cranelift",
|
||||
"wasmer-compiler-llvm",
|
||||
"wasmer-compiler-singlepass",
|
||||
"wasmer-engine",
|
||||
"wasmer-jit",
|
||||
"wasmer-wasi",
|
||||
"wasmer-wasi-experimental-io-devices",
|
||||
@@ -1574,6 +1582,27 @@ dependencies = [
|
||||
"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]]
|
||||
name = "wasmer-jit"
|
||||
version = "0.16.2"
|
||||
@@ -1590,6 +1619,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"wasm-common",
|
||||
"wasmer-compiler",
|
||||
"wasmer-engine",
|
||||
"wasmer-runtime",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
@@ -25,6 +25,7 @@ wasmer-compiler = { path = "lib/compiler" }
|
||||
wasmer-compiler-cranelift = { path = "lib/compiler-cranelift", optional = true }
|
||||
wasmer-compiler-singlepass = { path = "lib/compiler-singlepass", optional = true }
|
||||
wasmer-compiler-llvm = { path = "lib/compiler-llvm", optional = true }
|
||||
wasmer-engine = { path = "lib/engine" }
|
||||
wasmer-jit = { path = "lib/jit" }
|
||||
wasmer-wasi = { path = "lib/wasi", 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-llvm = { path = "../compiler-llvm", version = "0.16.2", optional = true }
|
||||
wasmer-compiler = { path = "../compiler", version = "0.16.2" }
|
||||
wasmer-engine = { path = "../engine", version = "0.16.2" }
|
||||
wasmer-jit = { path = "../jit", version = "0.16.2" }
|
||||
wasm-common = { path = "../wasm-common", version = "0.16.2" }
|
||||
indexmap = { version = "1.3.2", features = ["serde-1"] }
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::{
|
||||
ffi::c_void,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use wasmer_jit::Resolver;
|
||||
use wasmer_engine::Resolver;
|
||||
use wasmer_runtime::Export;
|
||||
|
||||
/// 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::store::Store;
|
||||
use crate::InstantiationError;
|
||||
use wasmer_jit::Resolver;
|
||||
use wasmer_engine::Resolver;
|
||||
use wasmer_runtime::InstanceHandle;
|
||||
|
||||
/// A WebAssembly Instance is a stateful, executable
|
||||
|
||||
@@ -28,7 +28,7 @@ pub use crate::types::{
|
||||
|
||||
pub use wasm_common::{ValueType, WasmExternType, WasmTypeList};
|
||||
pub use wasmer_compiler::{CompilerConfig, Features, Target};
|
||||
pub use wasmer_jit::{
|
||||
pub use wasmer_engine::{
|
||||
DeserializeError, InstantiationError, LinkError, RuntimeError, SerializeError,
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use wasmer_compiler::{CompileError, WasmError};
|
||||
use wasmer_jit::{CompiledModule, DeserializeError, Resolver, SerializeError};
|
||||
use wasmer_engine::{CompiledModule, DeserializeError, Resolver, SerializeError};
|
||||
use wasmer_runtime::InstanceHandle;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
@@ -30,7 +30,7 @@ pub enum IoCompileError {
|
||||
#[derive(Clone)]
|
||||
pub struct Module {
|
||||
store: Store,
|
||||
compiled: Arc<CompiledModule>,
|
||||
compiled: Arc<dyn CompiledModule>,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
@@ -173,10 +173,11 @@ impl Module {
|
||||
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 {
|
||||
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 wasmer_runtime::{LinearMemory, Table};
|
||||
use wasmer_runtime::{MemoryPlan, MemoryStyle, TablePlan, TableStyle};
|
||||
use wasmer_engine::Tunables as BaseTunables;
|
||||
|
||||
/// Tunable parameters for WebAssembly compilation.
|
||||
#[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`
|
||||
fn memory_plan(&self, memory: MemoryType) -> MemoryPlan {
|
||||
// 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
|
||||
use crate::trap::RuntimeError;
|
||||
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" }
|
||||
wasmer-compiler = { path = "../compiler", version = "0.16.2", default-features = false }
|
||||
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 }
|
||||
# flexbuffers = { path = "../../../flatbuffers/rust/flexbuffers", version = "0.1.0" }
|
||||
backtrace = "0.3.46"
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
//! JIT compilation.
|
||||
|
||||
use crate::error::InstantiationError;
|
||||
use crate::resolver::Resolver;
|
||||
use crate::tunables::Tunables;
|
||||
use crate::CodeMemory;
|
||||
use crate::{CompiledModule, DeserializeError, SerializeError};
|
||||
use wasmer_engine::{Engine, InstantiationError, Resolver, Tunables, DeserializeError, SerializeError, CompiledModule as BaseCompiledModule};
|
||||
use crate::{CodeMemory, CompiledModule};
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
@@ -12,7 +9,7 @@ use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{FuncType, LocalFuncIndex, MemoryIndex, TableIndex};
|
||||
use wasmer_compiler::{
|
||||
Compilation, CompileError, Compiler as BaseCompiler, CompilerConfig, FunctionBody,
|
||||
FunctionBodyData, ModuleTranslationState, Target,
|
||||
FunctionBodyData, ModuleTranslationState,
|
||||
};
|
||||
use wasmer_runtime::{
|
||||
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> {
|
||||
self.inner.borrow()
|
||||
}
|
||||
@@ -57,6 +49,13 @@ impl JITEngine {
|
||||
self.inner.borrow_mut()
|
||||
}
|
||||
|
||||
|
||||
/// Get the tunables
|
||||
pub fn tunables(&self) -> &dyn Tunables {
|
||||
&**self.tunables
|
||||
}
|
||||
// }
|
||||
// impl Engine for JITEngine {
|
||||
/// Register a signature
|
||||
pub fn register_signature(&self, func_type: &FuncType) -> VMSharedSignatureIndex {
|
||||
let compiler = self.compiler();
|
||||
@@ -80,27 +79,30 @@ impl JITEngine {
|
||||
}
|
||||
|
||||
/// Compile a WebAssembly binary
|
||||
pub fn compile(&self, binary: &[u8]) -> Result<CompiledModule, CompileError> {
|
||||
CompiledModule::new(&self, binary)
|
||||
pub fn compile(&self, binary: &[u8]) -> Result<Arc<dyn BaseCompiledModule>, CompileError> {
|
||||
Ok(Arc::new(CompiledModule::new(&self, binary)?))
|
||||
}
|
||||
|
||||
/// Instantiates a WebAssembly module
|
||||
pub fn instantiate(
|
||||
&self,
|
||||
compiled_module: &CompiledModule,
|
||||
compiled_module: &Arc<dyn BaseCompiledModule>,
|
||||
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(())) }
|
||||
}
|
||||
|
||||
/// 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()
|
||||
}
|
||||
|
||||
/// Deserializes a WebAssembly module
|
||||
pub fn deserialize(&self, bytes: &[u8]) -> Result<CompiledModule, DeserializeError> {
|
||||
CompiledModule::deserialize(&self, bytes)
|
||||
pub fn deserialize(&self, bytes: &[u8]) -> Result<Arc<dyn BaseCompiledModule>, DeserializeError> {
|
||||
Ok(Arc::new(CompiledModule::deserialize(&self, bytes)?))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,28 +27,16 @@
|
||||
|
||||
mod code_memory;
|
||||
mod engine;
|
||||
mod error;
|
||||
mod function_table;
|
||||
mod link;
|
||||
mod module;
|
||||
mod resolver;
|
||||
mod serialize;
|
||||
mod trap;
|
||||
mod tunables;
|
||||
|
||||
pub use crate::code_memory::CodeMemory;
|
||||
pub use crate::engine::JITEngine;
|
||||
pub use crate::error::{
|
||||
DeserializeError, ImportError, InstantiationError, LinkError, SerializeError,
|
||||
};
|
||||
pub use crate::function_table::FunctionTable;
|
||||
pub use crate::link::link_module;
|
||||
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.
|
||||
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::VMFunctionBody;
|
||||
|
||||
/// Links a module that has been compiled with `compiled_module` in `wasmer-compiler::Compiler`.
|
||||
///
|
||||
/// Performs all required relocations inside the function code, provided the necessary metadata.
|
||||
/// Links a module, patching the allocated functions with the
|
||||
/// requiredd relocations and jump tables.
|
||||
pub fn link_module(
|
||||
module: &Module,
|
||||
allocated_functions: &PrimaryMap<LocalFuncIndex, *mut [VMFunctionBody]>,
|
||||
@@ -68,10 +67,8 @@ pub fn link_module(
|
||||
.wrapping_add(reloc_addend as u32);
|
||||
write_unaligned(reloc_address as *mut u32, reloc_delta_u32);
|
||||
}
|
||||
RelocationKind::X86PCRelRodata4 => {
|
||||
// ignore
|
||||
}
|
||||
_ => panic!("unsupported reloc kind"),
|
||||
RelocationKind::X86PCRelRodata4 => {}
|
||||
_ => panic!("Relocation kind unsupported"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,16 +4,14 @@
|
||||
//! steps.
|
||||
|
||||
use crate::engine::{JITEngine, JITEngineInner};
|
||||
use crate::error::{DeserializeError, SerializeError};
|
||||
use crate::error::{InstantiationError, LinkError};
|
||||
use crate::link::link_module;
|
||||
use crate::resolver::{resolve_imports, Resolver};
|
||||
use crate::serialize::{
|
||||
SerializableCompilation, SerializableFunctionFrameInfo, SerializableModule,
|
||||
use wasmer_engine::{DeserializeError, SerializeError, InstantiationError, LinkError, SerializableFunctionFrameInfo,
|
||||
resolve_imports, Resolver, register_frame_info, GlobalFrameInfoRegistration, RuntimeError,
|
||||
CompiledModule as BaseCompiledModule
|
||||
};
|
||||
use crate::link::link_module;
|
||||
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 std::any::Any;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@@ -168,15 +166,7 @@ impl CompiledModule {
|
||||
&self.serializable.table_plans
|
||||
}
|
||||
|
||||
/// Crate an `Instance` from this `CompiledModule`.
|
||||
///
|
||||
/// 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`
|
||||
/// Instantiate the module
|
||||
pub unsafe fn instantiate(
|
||||
&self,
|
||||
jit: &JITEngine,
|
||||
@@ -227,21 +217,6 @@ impl CompiledModule {
|
||||
.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.
|
||||
///
|
||||
/// 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.
|
||||
fn create_memories(
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use serde::de::{Deserializer, Visitor};
|
||||
use serde::ser::Serializer;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use wasmer_compiler::{CompiledFunctionFrameInfo, FunctionBody, JumpTableOffsets, Relocation};
|
||||
use wasmer_compiler::{FunctionBody, JumpTableOffsets, Relocation};
|
||||
use wasmer_runtime::Module;
|
||||
|
||||
use wasmer_engine::SerializableFunctionFrameInfo;
|
||||
use wasm_common::entity::PrimaryMap;
|
||||
use wasm_common::{LocalFuncIndex, MemoryIndex, OwnedDataInitializer, TableIndex};
|
||||
use wasmer_runtime::{MemoryPlan, TablePlan};
|
||||
@@ -33,105 +30,3 @@ pub struct SerializableModule {
|
||||
pub memory_plans: PrimaryMap<MemoryIndex, MemoryPlan>,
|
||||
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