Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/compile not in memory #3573

Merged
merged 8 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions lib/api/src/sys/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ pub enum InstantiationError {
/// This error occurs when an import from a different store is used.
#[error("cannot mix imports from different stores")]
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 {
Expand Down
5 changes: 5 additions & 0 deletions lib/api/src/sys/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,11 @@ impl Module {
store: &mut impl AsStoreMut,
imports: &[crate::Extern],
) -> 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.
for import in imports {
if !import.is_from_store(store) {
Expand Down
6 changes: 6 additions & 0 deletions lib/c-api/src/wasm_c_api/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ pub unsafe extern "C" fn wasm_instance_new(

return None;
}

Err(e @ InstantiationError::DifferentArchOS) => {
ptitSeb marked this conversation as resolved.
Show resolved Hide resolved
crate::error::update_last_error(e);

return None;
}
};

Some(Box::new(wasm_instance_t {
Expand Down
113 changes: 85 additions & 28 deletions lib/compiler/src/engine/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
use wasmer_types::compilation::symbols::ModuleMetadata;
use wasmer_types::entity::{BoxedSlice, PrimaryMap};
#[cfg(feature = "static-artifact-create")]
use wasmer_types::CompileModuleInfo;
use wasmer_types::MetadataHeader;
#[cfg(feature = "static-artifact-load")]
use wasmer_types::SerializableCompilation;
use wasmer_types::{
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_vm::{FunctionBodyPtr, MemoryStyle, TableStyle, VMSharedSignatureIndex, VMTrampoline};
use wasmer_vm::{InstanceAllocator, StoreObjects, TrapHandlerFn, VMExtern, VMInstance};

/// A compiled wasm module, ready to be instantiated.
pub struct Artifact {
artifact: ArtifactBuild,
pub struct AllocatedArtifact {
finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
Expand All @@ -48,6 +46,14 @@ pub struct Artifact {
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 {
/// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
#[cfg(feature = "compiler")]
Expand Down Expand Up @@ -79,7 +85,14 @@ impl Artifact {
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.
Expand Down Expand Up @@ -120,14 +133,22 @@ impl Artifact {
let serializable = SerializableModule::deserialize(metadata_slice)?;
let artifact = ArtifactBuild::from_serializable(serializable);
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.
pub fn from_parts(
engine_inner: &mut EngineInner,
artifact: ArtifactBuild,
target: &Target,
) -> Result<Self, CompileError> {
if !target.is_native() {
return Ok(Self {
artifact,
allocated: None,
});
}
let module_info = artifact.create_module_info();
let (
finished_functions,
Expand Down Expand Up @@ -198,12 +219,14 @@ impl Artifact {

Ok(Self {
artifact,
finished_functions,
finished_function_call_trampolines,
finished_dynamic_function_trampolines,
signatures,
frame_info_registration: Some(Mutex::new(None)),
finished_function_lengths,
allocated: Some(AllocatedArtifact {
finished_functions,
finished_function_call_trampolines,
finished_dynamic_function_trampolines,
signatures,
frame_info_registration: Some(Mutex::new(None)),
finished_function_lengths,
}),
})
}

Expand Down Expand Up @@ -248,18 +271,34 @@ impl Artifact {
///
/// This is required to ensure that any traps can be properly symbolicated.
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();

if info.is_some() {
return;
}

let finished_function_extents = self
.allocated
.as_ref()
.expect("It must be allocated")
.finished_functions
.values()
.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 })
.collect::<PrimaryMap<LocalFunctionIndex, _>>()
.into_boxed_slice();
Expand All @@ -276,26 +315,42 @@ impl Artifact {
/// Returns the functions allocated in memory or this `Artifact`
/// ready to be run.
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
/// `Artifact`, ready to be run.
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
/// of this `Artifact`, ready to be run.
pub fn finished_dynamic_function_trampolines(
&self,
) -> &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`.
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
Expand Down Expand Up @@ -721,14 +776,16 @@ impl Artifact {

Ok(Self {
artifact,
finished_functions: finished_functions.into_boxed_slice(),
finished_function_call_trampolines: finished_function_call_trampolines
.into_boxed_slice(),
finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
.into_boxed_slice(),
signatures: signatures.into_boxed_slice(),
finished_function_lengths,
frame_info_registration: None,
allocated: Some(AllocatedArtifact {
finished_functions: finished_functions.into_boxed_slice(),
finished_function_call_trampolines: finished_function_call_trampolines
.into_boxed_slice(),
finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
.into_boxed_slice(),
signatures: signatures.into_boxed_slice(),
finished_function_lengths,
frame_info_registration: None,
}),
})
}
}
7 changes: 7 additions & 0 deletions lib/types/src/compilation/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ impl Target {
pub fn cpu_features(&self) -> &EnumSet<CpuFeature> {
&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
ptitSeb marked this conversation as resolved.
Show resolved Hide resolved
}
}

/// The default for the Target will use the HOST as the triple
Expand Down
1 change: 1 addition & 0 deletions tests/compilers/traps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> {
match err {
InstantiationError::Link(_)
| InstantiationError::DifferentStores
| InstantiationError::DifferentArchOS
| InstantiationError::CpuFeature(_) => {
panic!("It should be a start error")
}
Expand Down