mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-16 17:18:57 +00:00
Fix/compile not in memory (#3573)
* Example of allocated artifact * Better error when Instancing fail because of OS/Arch issue * Add missing brnach for new error --------- Co-authored-by: Syrus Akbary <me@syrusakbary.com>
This commit is contained in:
@@ -67,6 +67,11 @@ pub enum InstantiationError {
|
|||||||
/// This error occurs when an import from a different store is used.
|
/// This error occurs when an import from a different store is used.
|
||||||
#[error("cannot mix imports from different stores")]
|
#[error("cannot mix imports from different stores")]
|
||||||
DifferentStores,
|
DifferentStores,
|
||||||
|
|
||||||
|
/// Import from a different Store.
|
||||||
|
/// This error occurs when an import from a different store is used.
|
||||||
|
#[error("incorrect OS or architecture")]
|
||||||
|
DifferentArchOS,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<wasmer_compiler::InstantiationError> for InstantiationError {
|
impl From<wasmer_compiler::InstantiationError> for InstantiationError {
|
||||||
|
|||||||
@@ -317,6 +317,11 @@ impl Module {
|
|||||||
store: &mut impl AsStoreMut,
|
store: &mut impl AsStoreMut,
|
||||||
imports: &[crate::Extern],
|
imports: &[crate::Extern],
|
||||||
) -> Result<VMInstance, InstantiationError> {
|
) -> Result<VMInstance, InstantiationError> {
|
||||||
|
if !self.artifact.allocated() {
|
||||||
|
// Return an error mentioning that the artifact is compiled for a different
|
||||||
|
// platform.
|
||||||
|
return Err(InstantiationError::DifferentArchOS);
|
||||||
|
}
|
||||||
// Ensure all imports come from the same context.
|
// Ensure all imports come from the same context.
|
||||||
for import in imports {
|
for import in imports {
|
||||||
if !import.is_from_store(store) {
|
if !import.is_from_store(store) {
|
||||||
|
|||||||
@@ -85,6 +85,12 @@ pub unsafe extern "C" fn wasm_instance_new(
|
|||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Err(e @ InstantiationError::DifferentArchOS) => {
|
||||||
|
crate::error::update_last_error(e);
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Box::new(wasm_instance_t {
|
Some(Box::new(wasm_instance_t {
|
||||||
|
|||||||
@@ -23,22 +23,20 @@ use wasmer_object::{emit_compilation, emit_data, get_object_for_target, Object};
|
|||||||
#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
|
#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
|
||||||
use wasmer_types::compilation::symbols::ModuleMetadata;
|
use wasmer_types::compilation::symbols::ModuleMetadata;
|
||||||
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
|
||||||
|
#[cfg(feature = "static-artifact-create")]
|
||||||
|
use wasmer_types::CompileModuleInfo;
|
||||||
use wasmer_types::MetadataHeader;
|
use wasmer_types::MetadataHeader;
|
||||||
#[cfg(feature = "static-artifact-load")]
|
#[cfg(feature = "static-artifact-load")]
|
||||||
use wasmer_types::SerializableCompilation;
|
use wasmer_types::SerializableCompilation;
|
||||||
use wasmer_types::{
|
use wasmer_types::{
|
||||||
CompileError, CpuFeature, DataInitializer, DeserializeError, FunctionIndex, LocalFunctionIndex,
|
CompileError, CpuFeature, DataInitializer, DeserializeError, FunctionIndex, LocalFunctionIndex,
|
||||||
MemoryIndex, ModuleInfo, OwnedDataInitializer, SignatureIndex, TableIndex,
|
MemoryIndex, ModuleInfo, OwnedDataInitializer, SignatureIndex, TableIndex, Target,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "static-artifact-create")]
|
|
||||||
use wasmer_types::{CompileModuleInfo, Target};
|
|
||||||
use wasmer_types::{SerializableModule, SerializeError};
|
use wasmer_types::{SerializableModule, SerializeError};
|
||||||
use wasmer_vm::{FunctionBodyPtr, MemoryStyle, TableStyle, VMSharedSignatureIndex, VMTrampoline};
|
use wasmer_vm::{FunctionBodyPtr, MemoryStyle, TableStyle, VMSharedSignatureIndex, VMTrampoline};
|
||||||
use wasmer_vm::{InstanceAllocator, StoreObjects, TrapHandlerFn, VMExtern, VMInstance};
|
use wasmer_vm::{InstanceAllocator, StoreObjects, TrapHandlerFn, VMExtern, VMInstance};
|
||||||
|
|
||||||
/// A compiled wasm module, ready to be instantiated.
|
pub struct AllocatedArtifact {
|
||||||
pub struct Artifact {
|
|
||||||
artifact: ArtifactBuild,
|
|
||||||
finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
|
finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
|
||||||
finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
|
finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
|
||||||
finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
|
finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
|
||||||
@@ -48,6 +46,14 @@ pub struct Artifact {
|
|||||||
finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
|
finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A compiled wasm module, ready to be instantiated.
|
||||||
|
pub struct Artifact {
|
||||||
|
artifact: ArtifactBuild,
|
||||||
|
// The artifact will only be allocated in memory in case we can execute it
|
||||||
|
// (that means, if the target != host then this will be None).
|
||||||
|
allocated: Option<AllocatedArtifact>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Artifact {
|
impl Artifact {
|
||||||
/// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
|
/// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
@@ -79,7 +85,14 @@ impl Artifact {
|
|||||||
table_styles,
|
table_styles,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Self::from_parts(&mut inner_engine, artifact)
|
Self::from_parts(&mut inner_engine, artifact, engine.target())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This indicates if the Artifact is allocated and can be run by the current
|
||||||
|
/// host. In case it can't be run (for example, if the artifact is cross compiled to
|
||||||
|
/// other architecture), it will return false.
|
||||||
|
pub fn allocated(&self) -> bool {
|
||||||
|
self.allocated.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
|
/// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
|
||||||
@@ -120,14 +133,22 @@ impl Artifact {
|
|||||||
let serializable = SerializableModule::deserialize(metadata_slice)?;
|
let serializable = SerializableModule::deserialize(metadata_slice)?;
|
||||||
let artifact = ArtifactBuild::from_serializable(serializable);
|
let artifact = ArtifactBuild::from_serializable(serializable);
|
||||||
let mut inner_engine = engine.inner_mut();
|
let mut inner_engine = engine.inner_mut();
|
||||||
Self::from_parts(&mut inner_engine, artifact).map_err(DeserializeError::Compiler)
|
Self::from_parts(&mut inner_engine, artifact, engine.target())
|
||||||
|
.map_err(DeserializeError::Compiler)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct a `ArtifactBuild` from component parts.
|
/// Construct a `ArtifactBuild` from component parts.
|
||||||
pub fn from_parts(
|
pub fn from_parts(
|
||||||
engine_inner: &mut EngineInner,
|
engine_inner: &mut EngineInner,
|
||||||
artifact: ArtifactBuild,
|
artifact: ArtifactBuild,
|
||||||
|
target: &Target,
|
||||||
) -> Result<Self, CompileError> {
|
) -> Result<Self, CompileError> {
|
||||||
|
if !target.is_native() {
|
||||||
|
return Ok(Self {
|
||||||
|
artifact,
|
||||||
|
allocated: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
let module_info = artifact.create_module_info();
|
let module_info = artifact.create_module_info();
|
||||||
let (
|
let (
|
||||||
finished_functions,
|
finished_functions,
|
||||||
@@ -198,12 +219,14 @@ impl Artifact {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
artifact,
|
artifact,
|
||||||
finished_functions,
|
allocated: Some(AllocatedArtifact {
|
||||||
finished_function_call_trampolines,
|
finished_functions,
|
||||||
finished_dynamic_function_trampolines,
|
finished_function_call_trampolines,
|
||||||
signatures,
|
finished_dynamic_function_trampolines,
|
||||||
frame_info_registration: Some(Mutex::new(None)),
|
signatures,
|
||||||
finished_function_lengths,
|
frame_info_registration: Some(Mutex::new(None)),
|
||||||
|
finished_function_lengths,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +271,13 @@ impl Artifact {
|
|||||||
///
|
///
|
||||||
/// This is required to ensure that any traps can be properly symbolicated.
|
/// This is required to ensure that any traps can be properly symbolicated.
|
||||||
pub fn register_frame_info(&self) {
|
pub fn register_frame_info(&self) {
|
||||||
if let Some(frame_info_registration) = self.frame_info_registration.as_ref() {
|
if let Some(frame_info_registration) = self
|
||||||
|
.allocated
|
||||||
|
.as_ref()
|
||||||
|
.expect("It must be allocated")
|
||||||
|
.frame_info_registration
|
||||||
|
.as_ref()
|
||||||
|
{
|
||||||
let mut info = frame_info_registration.lock().unwrap();
|
let mut info = frame_info_registration.lock().unwrap();
|
||||||
|
|
||||||
if info.is_some() {
|
if info.is_some() {
|
||||||
@@ -256,10 +285,20 @@ impl Artifact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let finished_function_extents = self
|
let finished_function_extents = self
|
||||||
|
.allocated
|
||||||
|
.as_ref()
|
||||||
|
.expect("It must be allocated")
|
||||||
.finished_functions
|
.finished_functions
|
||||||
.values()
|
.values()
|
||||||
.copied()
|
.copied()
|
||||||
.zip(self.finished_function_lengths.values().copied())
|
.zip(
|
||||||
|
self.allocated
|
||||||
|
.as_ref()
|
||||||
|
.expect("It must be allocated")
|
||||||
|
.finished_function_lengths
|
||||||
|
.values()
|
||||||
|
.copied(),
|
||||||
|
)
|
||||||
.map(|(ptr, length)| FunctionExtent { ptr, length })
|
.map(|(ptr, length)| FunctionExtent { ptr, length })
|
||||||
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
|
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
|
||||||
.into_boxed_slice();
|
.into_boxed_slice();
|
||||||
@@ -276,13 +315,21 @@ impl Artifact {
|
|||||||
/// Returns the functions allocated in memory or this `Artifact`
|
/// Returns the functions allocated in memory or this `Artifact`
|
||||||
/// ready to be run.
|
/// ready to be run.
|
||||||
pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
|
pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
|
||||||
&self.finished_functions
|
&self
|
||||||
|
.allocated
|
||||||
|
.as_ref()
|
||||||
|
.expect("It must be allocated")
|
||||||
|
.finished_functions
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the function call trampolines allocated in memory of this
|
/// Returns the function call trampolines allocated in memory of this
|
||||||
/// `Artifact`, ready to be run.
|
/// `Artifact`, ready to be run.
|
||||||
pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
|
pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
|
||||||
&self.finished_function_call_trampolines
|
&self
|
||||||
|
.allocated
|
||||||
|
.as_ref()
|
||||||
|
.expect("It must be allocated")
|
||||||
|
.finished_function_call_trampolines
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the dynamic function trampolines allocated in memory
|
/// Returns the dynamic function trampolines allocated in memory
|
||||||
@@ -290,12 +337,20 @@ impl Artifact {
|
|||||||
pub fn finished_dynamic_function_trampolines(
|
pub fn finished_dynamic_function_trampolines(
|
||||||
&self,
|
&self,
|
||||||
) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
|
) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
|
||||||
&self.finished_dynamic_function_trampolines
|
&self
|
||||||
|
.allocated
|
||||||
|
.as_ref()
|
||||||
|
.expect("It must be allocated")
|
||||||
|
.finished_dynamic_function_trampolines
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the associated VM signatures for this `Artifact`.
|
/// Returns the associated VM signatures for this `Artifact`.
|
||||||
pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
|
pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
|
||||||
&self.signatures
|
&self
|
||||||
|
.allocated
|
||||||
|
.as_ref()
|
||||||
|
.expect("It must be allocated")
|
||||||
|
.signatures
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Do preinstantiation logic that is executed before instantiating
|
/// Do preinstantiation logic that is executed before instantiating
|
||||||
@@ -721,14 +776,16 @@ impl Artifact {
|
|||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
artifact,
|
artifact,
|
||||||
finished_functions: finished_functions.into_boxed_slice(),
|
allocated: Some(AllocatedArtifact {
|
||||||
finished_function_call_trampolines: finished_function_call_trampolines
|
finished_functions: finished_functions.into_boxed_slice(),
|
||||||
.into_boxed_slice(),
|
finished_function_call_trampolines: finished_function_call_trampolines
|
||||||
finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
|
.into_boxed_slice(),
|
||||||
.into_boxed_slice(),
|
finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
|
||||||
signatures: signatures.into_boxed_slice(),
|
.into_boxed_slice(),
|
||||||
finished_function_lengths,
|
signatures: signatures.into_boxed_slice(),
|
||||||
frame_info_registration: None,
|
finished_function_lengths,
|
||||||
|
frame_info_registration: None,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -192,6 +192,13 @@ impl Target {
|
|||||||
pub fn cpu_features(&self) -> &EnumSet<CpuFeature> {
|
pub fn cpu_features(&self) -> &EnumSet<CpuFeature> {
|
||||||
&self.cpu_features
|
&self.cpu_features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if target is a native (eq to host) or not
|
||||||
|
pub fn is_native(&self) -> bool {
|
||||||
|
let host = Triple::host();
|
||||||
|
host.operating_system == self.triple.operating_system
|
||||||
|
&& host.architecture == self.triple.architecture
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The default for the Target will use the HOST as the triple
|
/// The default for the Target will use the HOST as the triple
|
||||||
|
|||||||
@@ -273,6 +273,7 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> {
|
|||||||
match err {
|
match err {
|
||||||
InstantiationError::Link(_)
|
InstantiationError::Link(_)
|
||||||
| InstantiationError::DifferentStores
|
| InstantiationError::DifferentStores
|
||||||
|
| InstantiationError::DifferentArchOS
|
||||||
| InstantiationError::CpuFeature(_) => {
|
| InstantiationError::CpuFeature(_) => {
|
||||||
panic!("It should be a start error")
|
panic!("It should be a start error")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user