///|
pub using @callable {type NativeCallableRegistry}
///|
#borrow(context, output)
extern "c" fn write_bound_entry_code(
context : JITContext,
target : Int64,
output : FixedArray[Byte],
) -> Int32 = "wasmoon_jit_write_bound_entry_code"
///|
/// A native entry bound to the instance environment that owns its code.
/// The leaf trampoline preserves all guest arguments and tail-call stack usage.
pub struct NativeCallable {
context : NativeJITContext
entry : InstalledTrampoline
}
///|
pub fn NativeJITContext::bind_callable(
self : NativeJITContext,
target : Int64,
) -> NativeCallable raise JitInstallError {
let bytes = FixedArray::make(40, b'\x00')
let size = write_bound_entry_code(self.handle, target, bytes)
if size <= 0 {
raise TrampolineAllocationFailed(code_size=0)
}
let code : Array[Int32] = []
for i in 0.. Int64 {
self.context |> ignore
self.entry.entry_address()
}
///|
pub fn NativeCallable::release(self : NativeCallable) -> Unit {
self.entry.release()
}
///|
/// Bind shared Store identities with this instance's local type and tag maps.
pub fn NativeJITContext::bind_callable_registry(
self : NativeJITContext,
registry : NativeCallableRegistry,
local_types : Array[Int32],
tags : Array[Int32],
functions~ : Array[Int32] = [],
) -> Unit {
let locals = FixedArray::make(local_types.length(), 0)
for i, value in local_types {
locals[i] = value
}
let tag_addresses = FixedArray::make(tags.length(), 0)
for i, address in tags {
tag_addresses[i] = address
}
self.handle.bind_callable_registry(
registry,
locals,
tag_addresses,
functions=FixedArray::makei(functions.length(), i => functions[i]),
)
}
///|
/// Install an independent callable view for a standalone context.
pub fn NativeJITContext::set_callable_types(
self : NativeJITContext,
local_types : Array[Int32],
parents : Array[Int32],
entries : Array[(Int64, Int32)],
tags : Array[Int32],
) -> Unit {
let registry = NativeCallableRegistry::new()
if !registry.replace(parents, entries) {
abort("failed to allocate native callable registry")
}
self.bind_callable_registry(registry, local_types, tags)
}