mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-09 06:08:29 +00:00
Move serialize into it’s own module
This commit is contained in:
@@ -14,15 +14,13 @@ use serde::{Deserialize, Serialize};
|
|||||||
use wasm_common::entity::PrimaryMap;
|
use wasm_common::entity::PrimaryMap;
|
||||||
use wasm_common::LocalFuncIndex;
|
use wasm_common::LocalFuncIndex;
|
||||||
|
|
||||||
type FunctionBody = Vec<u8>;
|
|
||||||
|
|
||||||
/// The frame info for a Compiled function.
|
/// The frame info for a Compiled function.
|
||||||
///
|
///
|
||||||
/// This structure is only used for reconstructing
|
/// This structure is only used for reconstructing
|
||||||
/// the frame information after a `Trap`.
|
/// the frame information after a `Trap`.
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
|
||||||
pub struct CompiledFunctionFrameInfo {
|
pub struct CompiledFunctionFrameInfo {
|
||||||
/// The traps (in the body)
|
/// The traps (in the function body)
|
||||||
pub traps: Vec<TrapInformation>,
|
pub traps: Vec<TrapInformation>,
|
||||||
|
|
||||||
/// The address map.
|
/// The address map.
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ use crate::error::{DeserializeError, SerializeError};
|
|||||||
use crate::error::{InstantiationError, LinkError};
|
use crate::error::{InstantiationError, LinkError};
|
||||||
use crate::link::link_module;
|
use crate::link::link_module;
|
||||||
use crate::resolver::{resolve_imports, Resolver};
|
use crate::resolver::{resolve_imports, Resolver};
|
||||||
use crate::trap::register as register_frame_info;
|
use crate::serialize::CacheRawCompiledModule;
|
||||||
use crate::trap::GlobalFrameInfoRegistration;
|
use crate::trap::GlobalFrameInfoRegistration;
|
||||||
use crate::trap::RuntimeError;
|
use crate::trap::RuntimeError;
|
||||||
|
use crate::trap::{register as register_frame_info, ExtraFunctionInfo};
|
||||||
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};
|
||||||
@@ -20,7 +21,9 @@ use wasm_common::{
|
|||||||
LocalTableIndex, MemoryIndex, SignatureIndex, TableIndex,
|
LocalTableIndex, MemoryIndex, SignatureIndex, TableIndex,
|
||||||
};
|
};
|
||||||
use wasmer_compiler::ModuleEnvironment;
|
use wasmer_compiler::ModuleEnvironment;
|
||||||
use wasmer_compiler::{Compilation, CompileError, FunctionAddressMap, TrapInformation};
|
use wasmer_compiler::{
|
||||||
|
Compilation, CompileError, CompiledFunctionFrameInfo, FunctionAddressMap, TrapInformation,
|
||||||
|
};
|
||||||
use wasmer_runtime::{
|
use wasmer_runtime::{
|
||||||
InstanceHandle, LinearMemory, Module, SignatureRegistry, Table, VMFunctionBody,
|
InstanceHandle, LinearMemory, Module, SignatureRegistry, Table, VMFunctionBody,
|
||||||
VMGlobalDefinition, VMSharedSignatureIndex,
|
VMGlobalDefinition, VMSharedSignatureIndex,
|
||||||
@@ -28,17 +31,6 @@ use wasmer_runtime::{
|
|||||||
|
|
||||||
use wasmer_runtime::{MemoryPlan, TablePlan};
|
use wasmer_runtime::{MemoryPlan, TablePlan};
|
||||||
|
|
||||||
/// Structure to cache the content ot the compilation
|
|
||||||
#[derive(Serialize, Deserialize)]
|
|
||||||
struct CacheRawCompiledModule {
|
|
||||||
compilation: Arc<Compilation>,
|
|
||||||
module: Arc<Module>,
|
|
||||||
data_initializers: Arc<Box<[OwnedDataInitializer]>>,
|
|
||||||
// Plans for that module
|
|
||||||
memory_plans: PrimaryMap<MemoryIndex, MemoryPlan>,
|
|
||||||
table_plans: PrimaryMap<TableIndex, TablePlan>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is similar to `CompiledModule`, but references the data initializers
|
/// This is similar to `CompiledModule`, but references the data initializers
|
||||||
/// from the wasm buffer rather than holding its own copy.
|
/// from the wasm buffer rather than holding its own copy.
|
||||||
struct RawCompiledModule {
|
struct RawCompiledModule {
|
||||||
@@ -337,7 +329,20 @@ impl CompiledModule {
|
|||||||
if info.is_some() {
|
if info.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
*info = Some(register_frame_info(&self));
|
|
||||||
|
let extra_functions = self
|
||||||
|
.traps()
|
||||||
|
.values()
|
||||||
|
.zip(self.address_transform().values())
|
||||||
|
.map(|(traps, instrs)| {
|
||||||
|
ExtraFunctionInfo::Processed(CompiledFunctionFrameInfo {
|
||||||
|
traps: traps.to_vec(),
|
||||||
|
address_map: (*instrs).clone(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<PrimaryMap<LocalFuncIndex, _>>();
|
||||||
|
|
||||||
|
*info = Some(register_frame_info(&self, extra_functions));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the a map for all traps in this module.
|
/// Returns the a map for all traps in this module.
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ mod function_table;
|
|||||||
mod instantiate;
|
mod instantiate;
|
||||||
mod link;
|
mod link;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
|
mod serialize;
|
||||||
mod trap;
|
mod trap;
|
||||||
mod tunables;
|
mod tunables;
|
||||||
|
|
||||||
|
|||||||
39
lib/jit/src/serialize.rs
Normal file
39
lib/jit/src/serialize.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
use crate::instantiate::OwnedDataInitializer;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use wasmer_compiler::Compilation;
|
||||||
|
use wasmer_runtime::Module;
|
||||||
|
|
||||||
|
use wasm_common::entity::PrimaryMap;
|
||||||
|
use wasm_common::{MemoryIndex, TableIndex};
|
||||||
|
use wasmer_runtime::{MemoryPlan, TablePlan};
|
||||||
|
|
||||||
|
// #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
|
// pub struct CompiledFunction {
|
||||||
|
// /// The function body.
|
||||||
|
// #[serde(with = "serde_bytes")]
|
||||||
|
// pub body: Vec<u8>,
|
||||||
|
|
||||||
|
// /// The relocations (in the body)
|
||||||
|
// pub relocations: Vec<Relocation>,
|
||||||
|
|
||||||
|
// /// The jump tables offsets (in the body).
|
||||||
|
// pub jt_offsets: JumpTableOffsets,
|
||||||
|
|
||||||
|
// /// The unwind information.
|
||||||
|
// pub unwind_info: CompiledFunctionUnwindInfo,
|
||||||
|
|
||||||
|
// /// The frame information.
|
||||||
|
// pub frame_info: CompiledFunctionFrameInfo,
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// Structure to cache the content ot the compilation
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct CacheRawCompiledModule {
|
||||||
|
pub compilation: Arc<Compilation>,
|
||||||
|
pub module: Arc<Module>,
|
||||||
|
pub data_initializers: Arc<Box<[OwnedDataInitializer]>>,
|
||||||
|
// Plans for that module
|
||||||
|
pub memory_plans: PrimaryMap<MemoryIndex, MemoryPlan>,
|
||||||
|
pub table_plans: PrimaryMap<TableIndex, TablePlan>,
|
||||||
|
}
|
||||||
@@ -73,7 +73,24 @@ impl RuntimeError {
|
|||||||
code: TrapCode,
|
code: TrapCode,
|
||||||
backtrace: Backtrace,
|
backtrace: Backtrace,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let desc = code.message();
|
let desc = match code {
|
||||||
|
TrapCode::StackOverflow => "call stack exhausted",
|
||||||
|
TrapCode::HeapSetterOutOfBounds => "memory out of bounds: data segment does not fit",
|
||||||
|
TrapCode::HeapAccessOutOfBounds => "out of bounds memory access",
|
||||||
|
TrapCode::TableSetterOutOfBounds => {
|
||||||
|
"table out of bounds: elements segment does not fit"
|
||||||
|
}
|
||||||
|
TrapCode::TableAccessOutOfBounds => "undefined element: out of bounds table access",
|
||||||
|
TrapCode::OutOfBounds => "out of bounds",
|
||||||
|
TrapCode::IndirectCallToNull => "uninitialized element",
|
||||||
|
TrapCode::BadSignature => "indirect call type mismatch",
|
||||||
|
TrapCode::IntegerOverflow => "integer overflow",
|
||||||
|
TrapCode::IntegerDivisionByZero => "integer divide by zero",
|
||||||
|
TrapCode::BadConversionToInteger => "invalid conversion to integer",
|
||||||
|
TrapCode::UnreachableCodeReached => "unreachable",
|
||||||
|
TrapCode::Interrupt => "interrupt",
|
||||||
|
TrapCode::User(_) => unreachable!(),
|
||||||
|
};
|
||||||
let msg = format!("{}", desc);
|
let msg = format!("{}", desc);
|
||||||
Self::new_with_trace(info, trap_pc, msg, backtrace)
|
Self::new_with_trace(info, trap_pc, msg, backtrace)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ pub struct GlobalFrameInfoRegistration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The function debug info, but unprocessed
|
/// The function debug info, but unprocessed
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct ExtraFunctionInfoUnprocessed {
|
pub struct ExtraFunctionInfoUnprocessed {
|
||||||
#[serde(with = "serde_bytes")]
|
#[serde(with = "serde_bytes")]
|
||||||
bytes: Vec<u8>,
|
bytes: Vec<u8>,
|
||||||
@@ -85,11 +85,25 @@ impl Into<CompiledFunctionFrameInfo> for ExtraFunctionInfoUnprocessed {
|
|||||||
/// of compiling at the same time that emiting the JIT.
|
/// of compiling at the same time that emiting the JIT.
|
||||||
/// In that case, we don't need to deserialize/process anything
|
/// In that case, we don't need to deserialize/process anything
|
||||||
/// as the data is already in memory.
|
/// as the data is already in memory.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum ExtraFunctionInfo {
|
pub enum ExtraFunctionInfo {
|
||||||
|
/// the processed function
|
||||||
Processed(CompiledFunctionFrameInfo),
|
Processed(CompiledFunctionFrameInfo),
|
||||||
|
/// the unprocessed
|
||||||
Unprocessed(ExtraFunctionInfoUnprocessed),
|
Unprocessed(ExtraFunctionInfoUnprocessed),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ExtraFunctionInfo {
|
||||||
|
/// Returns true if the extra function info is not yet
|
||||||
|
/// processed
|
||||||
|
pub fn is_unprocessed(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Unprocessed(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ModuleFrameInfo {
|
struct ModuleFrameInfo {
|
||||||
start: usize,
|
start: usize,
|
||||||
functions: BTreeMap<usize, FunctionInfo>,
|
functions: BTreeMap<usize, FunctionInfo>,
|
||||||
@@ -102,6 +116,19 @@ impl ModuleFrameInfo {
|
|||||||
&self.extra_functions.get(local_index).unwrap()
|
&self.extra_functions.get(local_index).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn process_function_debug_info(&mut self, local_index: LocalFuncIndex) {
|
||||||
|
let mut func = self.extra_functions.get_mut(local_index).unwrap();
|
||||||
|
let processed: CompiledFunctionFrameInfo = match func {
|
||||||
|
ExtraFunctionInfo::Processed(_) => {
|
||||||
|
// This should be a no-op on processed info
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ExtraFunctionInfo::Unprocessed(unprocessed) => {
|
||||||
|
bincode::deserialize(&unprocessed.bytes).expect("Can't deserialize the info")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*func = ExtraFunctionInfo::Processed(processed)
|
||||||
|
}
|
||||||
fn instr_map(&self, local_index: LocalFuncIndex) -> &FunctionAddressMap {
|
fn instr_map(&self, local_index: LocalFuncIndex) -> &FunctionAddressMap {
|
||||||
match self.function_debug_info(local_index) {
|
match self.function_debug_info(local_index) {
|
||||||
ExtraFunctionInfo::Processed(di) => &di.address_map,
|
ExtraFunctionInfo::Processed(di) => &di.address_map,
|
||||||
@@ -138,8 +165,7 @@ impl GlobalFrameInfo {
|
|||||||
/// Returns an object if this `pc` is known to some previously registered
|
/// Returns an object if this `pc` is known to some previously registered
|
||||||
/// module, or returns `None` if no information can be found.
|
/// module, or returns `None` if no information can be found.
|
||||||
pub fn lookup_frame_info(&self, pc: usize) -> Option<FrameInfo> {
|
pub fn lookup_frame_info(&self, pc: usize) -> Option<FrameInfo> {
|
||||||
let module = self.module_info(pc)?;
|
let (module, func) = self.maybe_process_frame(pc)?;
|
||||||
let func = module.function_info(pc)?;
|
|
||||||
|
|
||||||
// Use our relative position from the start of the function to find the
|
// Use our relative position from the start of the function to find the
|
||||||
// machine instruction that corresponds to `pc`, which then allows us to
|
// machine instruction that corresponds to `pc`, which then allows us to
|
||||||
@@ -194,8 +220,7 @@ impl GlobalFrameInfo {
|
|||||||
|
|
||||||
/// Fetches trap information about a program counter in a backtrace.
|
/// Fetches trap information about a program counter in a backtrace.
|
||||||
pub fn lookup_trap_info(&self, pc: usize) -> Option<&TrapInformation> {
|
pub fn lookup_trap_info(&self, pc: usize) -> Option<&TrapInformation> {
|
||||||
let module = self.module_info(pc)?;
|
let (module, func) = self.maybe_process_frame(pc)?;
|
||||||
let func = module.function_info(pc)?;
|
|
||||||
let traps = module.traps(func.local_index);
|
let traps = module.traps(func.local_index);
|
||||||
let idx = traps
|
let idx = traps
|
||||||
.binary_search_by_key(&((pc - func.start) as u32), |info| info.code_offset)
|
.binary_search_by_key(&((pc - func.start) as u32), |info| info.code_offset)
|
||||||
@@ -203,6 +228,21 @@ impl GlobalFrameInfo {
|
|||||||
Some(&traps[idx])
|
Some(&traps[idx])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an process a Frame in case is not yet processed
|
||||||
|
fn maybe_process_frame(&self, pc: usize) -> Option<(&ModuleFrameInfo, &FunctionInfo)> {
|
||||||
|
let module = self.module_info(pc)?;
|
||||||
|
let func = module.function_info(pc)?;
|
||||||
|
let extra_func_info = module.function_debug_info(func.local_index);
|
||||||
|
if extra_func_info.is_unprocessed() {
|
||||||
|
let mut mutable_info = FRAME_INFO.write().unwrap();
|
||||||
|
let mut mutable_module = mutable_info.module_info_mut(pc)?;
|
||||||
|
mutable_module.process_function_debug_info(func.local_index);
|
||||||
|
let module = self.module_info(pc)?;
|
||||||
|
return Some((module, func));
|
||||||
|
}
|
||||||
|
Some((module, func))
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets a module given a pc
|
/// Gets a module given a pc
|
||||||
fn module_info(&self, pc: usize) -> Option<&ModuleFrameInfo> {
|
fn module_info(&self, pc: usize) -> Option<&ModuleFrameInfo> {
|
||||||
let (end, module_info) = self.ranges.range(pc..).next()?;
|
let (end, module_info) = self.ranges.range(pc..).next()?;
|
||||||
@@ -236,7 +276,10 @@ impl Drop for GlobalFrameInfoRegistration {
|
|||||||
/// compiled functions within `module`. If the `module` has no functions
|
/// compiled functions within `module`. If the `module` has no functions
|
||||||
/// then `None` will be returned. Otherwise the returned object, when
|
/// then `None` will be returned. Otherwise the returned object, when
|
||||||
/// dropped, will be used to unregister all name information from this map.
|
/// dropped, will be used to unregister all name information from this map.
|
||||||
pub fn register(module: &CompiledModule) -> Option<GlobalFrameInfoRegistration> {
|
pub fn register(
|
||||||
|
module: &CompiledModule,
|
||||||
|
extra_functions: PrimaryMap<LocalFuncIndex, ExtraFunctionInfo>,
|
||||||
|
) -> Option<GlobalFrameInfoRegistration> {
|
||||||
let mut min = usize::max_value();
|
let mut min = usize::max_value();
|
||||||
let mut max = 0;
|
let mut max = 0;
|
||||||
let mut functions = BTreeMap::new();
|
let mut functions = BTreeMap::new();
|
||||||
@@ -268,18 +311,6 @@ pub fn register(module: &CompiledModule) -> Option<GlobalFrameInfoRegistration>
|
|||||||
assert!(*prev_end < min);
|
assert!(*prev_end < min);
|
||||||
}
|
}
|
||||||
|
|
||||||
let extra_functions = module
|
|
||||||
.traps()
|
|
||||||
.values()
|
|
||||||
.zip(module.address_transform().values())
|
|
||||||
.map(|(traps, instrs)| {
|
|
||||||
ExtraFunctionInfo::Processed(CompiledFunctionFrameInfo {
|
|
||||||
traps: traps.to_vec(),
|
|
||||||
address_map: (*instrs).clone(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<PrimaryMap<LocalFuncIndex, _>>();
|
|
||||||
|
|
||||||
// ... then insert our range and assert nothing was there previously
|
// ... then insert our range and assert nothing was there previously
|
||||||
let prev = info.ranges.insert(
|
let prev = info.ranges.insert(
|
||||||
max,
|
max,
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
mod error;
|
mod error;
|
||||||
mod frame_info;
|
mod frame_info;
|
||||||
pub use error::RuntimeError;
|
pub use error::RuntimeError;
|
||||||
pub use frame_info::{register, FrameInfo, GlobalFrameInfoRegistration, FRAME_INFO};
|
pub use frame_info::{
|
||||||
|
register, ExtraFunctionInfo, ExtraFunctionInfoUnprocessed, FrameInfo,
|
||||||
|
GlobalFrameInfoRegistration, FRAME_INFO,
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user