///|
pub using @artifact_loader {
type ArtifactCompatibility,
type ArtifactIncompatible,
type ArtifactLoadError,
}
///|
/// Native preparation of a verified portable artifact. Instances retain the
/// immutable safepoint owner independently of this wrapper.
pub struct LoadedArtifact {
priv verified : @artifact_loader.LoadedArtifact
priv safepoints : @jit_ffi.PreparedSafepoints?
}
///|
fn prepare_loaded_artifact(
verified : @artifact_loader.LoadedArtifact,
) -> LoadedArtifact raise ArtifactLoadError {
let functions = verified.artifact().functions
let safepoints = if functions.any(f => !f.safepoints.is_empty()) {
let mut count = 0
for function in functions {
if !function.safepoints.is_empty() {
count = Int32::max(count, function.identity.function_index + 1)
}
}
@jit_ffi.PreparedSafepoints::check_count(count) catch {
error =>
raise @artifact_loader.ArtifactLoadError::native_preparation_failed(
error.to_string(),
)
}
let blobs = FixedArray::make(count, b"")
let offsets : FixedArray[FixedArray[Int32]] = FixedArray::make(count, [])
for function in functions {
if !function.safepoints.is_empty() {
let (blob, sites) = prepare_code_object_safepoints(function.safepoints)
blobs[function.identity.function_index] = blob
offsets[function.identity.function_index] = sites
}
}
Some(
@jit_ffi.PreparedSafepoints::new(blobs, offsets) catch {
error =>
raise @artifact_loader.ArtifactLoadError::native_preparation_failed(
error.to_string(),
)
},
)
} else {
None
}
{ verified, safepoints, }
}
///|
pub fn verify_artifact(
artifact : @artifact.Artifact,
compatibility : ArtifactCompatibility,
) -> LoadedArtifact raise ArtifactLoadError {
prepare_loaded_artifact(
@artifact_loader.verify_artifact(artifact, compatibility),
)
}
///|
pub fn load_artifact(
bytes : Bytes,
compatibility : ArtifactCompatibility,
limits~ : @artifact.DecodeLimits = @artifact.DecodeLimits::default(),
) -> LoadedArtifact raise ArtifactLoadError {
prepare_loaded_artifact(
@artifact_loader.load_artifact(bytes, compatibility, limits~),
)
}
///|
/// Portable verified input for code installation and inspection.
pub fn LoadedArtifact::verified(
self : LoadedArtifact,
) -> @artifact_loader.LoadedArtifact {
self.verified
}
///|
pub fn LoadedArtifact::artifact(self : LoadedArtifact) -> @artifact.Artifact {
self.verified.artifact()
}
///|
pub fn LoadedArtifact::code_objects(
self : LoadedArtifact,
) -> Array[@code_object.UnlinkedCodeObject] {
self.verified.code_objects()
}
///|
pub fn LoadedArtifact::context_layout(self : LoadedArtifact) -> ContextLayout? {
self.verified.context_layout()
}
///|
/// Bind only to a fresh context, before any invocation can reference its metadata.
pub fn LoadedArtifact::bind_safepoints(
self : LoadedArtifact,
context : NativeJITContext,
) -> Bool {
match self.safepoints {
Some(prepared) => context.handle.bind_prepared_safepoints(prepared)
None => true
}
}