///|
pub using @runtime_bridge {
memory_descriptor_length,
memory_descriptor_grow,
memory_descriptor_read,
memory_descriptor_write,
memory_descriptor_write_bytes,
memory_descriptor_move,
memory_descriptor_fill,
type MemoryInfo,
alloc_memory,
alloc_memory_desc,
alloc_guarded_memory_desc,
free_memory,
type JITTable,
type JITTableOwner,
memory_descriptor_copy,
memory_descriptor_fill64,
memory_descriptor_grow64,
type MemoryDescriptor,
type NativeTableHandle,
}
///|
fn context_func_table_ptr(context : JITContext) -> Int64 {
c_jit_ctx_get_func_table_managed(context)
}
///|
fn context_func_count(context : JITContext) -> Int32 {
c_jit_ctx_get_func_count_managed(context)
}
///|
fn context_table_ptr(
context : JITContext,
table_idx : Int32,
) -> NativeTableHandle {
c_jit_ctx_get_table_ptr_managed(context, table_idx)
}
///|
fn context_table_size(context : JITContext, table_idx : Int32) -> Int32 {
c_jit_ctx_get_table_size_managed(context, table_idx)
}
///|
pub fn NativeJITContext::set_memory(
self : NativeJITContext,
mem0_ptr : MemoryDescriptor,
) -> Unit {
c_jit_ctx_set_memory_managed(self.handle, mem0_ptr)
}
///|
pub fn NativeJITContext::alloc_guarded_memory(
self : NativeJITContext,
initial_pages : Int32,
max_pages : Int32?,
) -> MemoryDescriptor {
c_jit_ctx_alloc_guarded_memory_managed(
self.handle,
initial_pages.to_int64(),
max_pages.unwrap_or(-1).to_int64(),
)
}
///|
pub fn NativeJITContext::func_ptr(
self : NativeJITContext,
func_idx : Int32,
) -> Int64 {
let table_ptr = context_func_table_ptr(self.handle)
let count = context_func_count(self.handle)
if table_ptr != 0L && func_idx >= 0 && func_idx < count {
native_value_slot_read(table_ptr, func_idx)
} else {
0L
}
}
///|
pub fn NativeJITContext::set_table_pointers(
self : NativeJITContext,
jit_tables : Array[JITTable?],
) -> Unit raise NativeSetupError {
let replacement = jit_tables.copy()
let table_ptrs = FixedArray::make(
jit_tables.length(),
NativeTableHandle::null(),
)
let table_sizes = FixedArray::make(jit_tables.length(), 0)
let table_max_sizes = FixedArray::make(jit_tables.length(), -1L)
for i, jit_table_opt in jit_tables {
match jit_table_opt {
Some(jit_table) => {
table_ptrs[i] = jit_table.raw_ptr()
table_sizes[i] = jit_table.get_size()
table_max_sizes[i] = jit_table.get_max().unwrap_or(-1L)
}
None => ()
}
}
let status = c_jit_ctx_set_table_pointers_managed(
self.handle,
table_ptrs,
table_sizes,
table_max_sizes,
jit_tables.length(),
)
match status {
1 => ()
0 => raise TableBindingAllocationFailed
_ => raise InvalidBinding("table count exceeds layout or context is closed")
}
self.jit_tables.clear()
for table in replacement {
self.jit_tables.push(table)
}
}
///|
/// Refresh one borrowed table from the context it was registered with.
/// The context supplies both the table identity and its live C-side layout.
pub fn NativeJITContext::refresh_table_layout(
self : NativeJITContext,
table_idx : Int32,
) -> Bool {
if table_idx < 0 || table_idx >= self.jit_tables.length() {
return false
}
guard self.jit_tables[table_idx] is Some(jit_table) else { return false }
let table_ptr = context_table_ptr(self.handle, table_idx)
let size = context_table_size(self.handle, table_idx)
if jit_table.raw_ptr().is_null() || table_ptr.is_null() || size < 0 {
return false
}
jit_table.refresh_layout(table_ptr, size)
true
}
///|
pub fn NativeJITContext::set_memory_pointers(
self : NativeJITContext,
memories : Array[MemoryInfo],
) -> Unit raise NativeSetupError {
let ptrs = FixedArray::make(memories.length(), MemoryDescriptor::null())
for i, mem in memories {
ptrs[i] = mem.ptr
}
match
c_jit_ctx_set_memory_pointers_managed(self.handle, ptrs, memories.length()) {
1 => ()
0 => raise MemoryBindingAllocationFailed
_ =>
raise InvalidBinding("memory count exceeds layout or context is closed")
}
}
///|
/// Borrow a raw byte address. Use memory_descriptor for accesses that must
/// retain the allocation independently of this context.
pub fn NativeJITContext::memory_ptr(
self : NativeJITContext,
memidx : Int32,
) -> Int64 {
c_jit_ctx_get_memory_ptr_managed(self.handle, memidx)
}
///|
pub fn NativeJITContext::memory_size(
self : NativeJITContext,
memidx : Int32,
) -> Int64 {
c_jit_ctx_get_memory_size_managed(self.handle, memidx)
}
///|
/// Retain a bound memory independently of this context. Invalid indices return
/// an empty handle. Passing this handle to descriptor operations keeps the
/// allocation alive throughout the operation.
pub fn NativeJITContext::memory_descriptor(
self : NativeJITContext,
memidx : Int32,
) -> MemoryDescriptor {
c_jit_ctx_get_memory_descriptor_managed(self.handle, memidx)
}