Wasmoon-specific JIT integration and native runtime glue
///|
test "plan a small MilkIR function for x64 JIT integration" {
let signature = @milkir.Signature::Signature([I64, I64], [I64])
let milk = @milkir.Function::with_signature("add64", signature)
let lhs = milk.param(0).unwrap()
let rhs = milk.param(1).unwrap()
let sum = milk.new_value(I64)
let entry = milk.new_block([])
entry.append_inst(milk.new_inst(Scalar(IntBinary(Add)), [lhs, rhs], [sum]))
entry.set_terminator(Return([sum]))
let plan = plan_milkir_integration_for_target(milk, X64)
inspect(plan.entry_symbol, content="add64")
debug_inspect(plan.target, content="X64")
inspect(plan.object.get_bytes().length() > 0, content="true")
inspect(
native_glue_covers_jit_ffi_stubs(glue=plan.native_glue),
content="true",
)
}///|
test "serialize and restore a precompiled module" {
let mod_ = @cwasm.PrecompiledModule::PrecompiledModule(AArch64)
mod_.add_type([TYPE_I32], [TYPE_I32])
mod_.add_import("env", "host_inc", 1, 1)
let entry = @cwasm.CompiledEntry::CompiledEntry(0, "inc", [0xc3], 0, 0, 1, 1)
mod_.add_function(entry)
let encoded = mod_.serialize()
let decoded = @cwasm.deserialize(encoded)
debug_inspect(decoded.target, content="AArch64")
inspect(decoded.import_count(), content="1")
inspect(decoded.function_count(), content="1")
}pub(all) suberror CHeapError {
OutOfBoundsArrayAccess
NullReference
OutOfMemory
}pub suberror GCSetupError {
MissingJITContext
InvalidFuncCount(num_funcs~ : Int)
FuncTypeIndicesLengthMismatch(func_type_indices_len~ : Int, num_funcs~ : Int)
MissingFunctionTableContext(num_funcs~ : Int)
} derive(Debug)impl Show for GCSetupErrorimpl Show for JitPipelineErrorpub struct BacktraceFrame {
pc : Int64
name : String
offset : Int64
func_idx : Int
}fn CHeap::alloc_array(self : CHeap, type_idx : Int, len : Int, init_value : Value) -> Int raise CHeapErrorfn CHeap::alloc_array_from_values(self : CHeap, type_idx : Int, elements : Array[Value]) -> Int raise CHeapErrorfn CHeap::array_copy(self : CHeap, dst_idx : Int, dst_offset : Int, src_idx : Int, src_offset : Int, count : Int) -> Unit raise CHeapErrorfn CHeap::array_fill(self : CHeap, array_idx : Int, offset : Int, value : Value, count : Int) -> Unit raise CHeapErrorfn CHeap::array_get(self : CHeap, array_idx : Int, elem_idx : Int, elem_type : ValueType) -> Value raise CHeapErrorfn CHeap::array_set(self : CHeap, array_idx : Int, elem_idx : Int, value : Value) -> Unit raise CHeapErrortype CodeCachepub(all) enum CompilationMode {
Interpret
Baseline
Optimized
}impl Show for CompilationModefn CompilationRequest::CompilationRequest(func_idx : Int, mode : CompilationMode) -> CompilationRequestfn CompilationRequest::with_priority(func_idx : Int, mode : CompilationMode, priority : Int) -> CompilationRequestpub(all) struct CompilationStrategy {
profiler : Profiler
queue : CompilationQueue
config : TieredConfig
decisions_interpret : Int
decisions_compile : Int
decisions_compiled : Int
}impl Show for CompilationStrategyfn CompilationStrategy::schedule_compilation(self : CompilationStrategy, func_idx : Int, mode : CompilationMode) -> Boolpub struct CompiledFunction {
name : String
code : MachineCode
entry_offset : Int
code_size : Int
frame_size : Int
gc_safepoints : Array[GcSafepoint]
gc_stackmap_blob : Bytes
valid : Bool
}impl Show for CompiledFunctionfn CompiledFunction::CompiledFunction(name : String, code : MachineCode, frame_size : Int, gc_safepoints? : Array[GcSafepoint], gc_stackmap_blob? : Bytes) -> CompiledFunctionpub(all) struct CwasmArtifact {
version : Int
target : TargetArch
entry_symbol : String
code : Array[Int]
functions : Array[CwasmFunctionRecord]
call_veneers : Array[CwasmCallVeneer]
runtime_relocations : Array[ResolvedRuntimeRelocation]
func_addr_fixups : Array[FuncAddrFixup]
call_fixups : Array[CallFixup]
gc_safepoints : Array[GcSafepoint]
gc_stackmap_blob : Bytes
} derive(Debug)fn CwasmArtifact::from_jit_plan(plan : JitIntegrationPlan, resolver : RuntimeSymbolResolver, function_index : Int) -> CwasmArtifact raise LinkErrorfn CwasmArtifact::from_jit_plan_with_signature(plan : JitIntegrationPlan, resolver : RuntimeSymbolResolver, function_index : Int, num_params : Int, num_results : Int) -> CwasmArtifact raise LinkErrorfn CwasmArtifact::from_linked_code_for_target(linked : LinkedCode, function_index : Int, target : TargetArch, entry_symbol : String) -> CwasmArtifactfn CwasmArtifact::from_linked_code_for_target_with_signature(linked : LinkedCode, function_index : Int, target : TargetArch, entry_symbol : String, num_params : Int, num_results : Int) -> CwasmArtifactpub struct DWARFBuilder {
// private fields
}fn DWARFBuilder::add_function(self : DWARFBuilder, name : String, addr : Int64, size : Int, func_idx : Int) -> Unittype ExecCodetype ExecutableRegionimpl Show for ExecutableRegionpub struct FunctionInfo {
name : String
func_idx : Int
offset : Int64
}pub(all) enum FunctionTemperature {
Cold
Warm
Hot
}impl Show for FunctionTemperaturefn GcSafepoint::GcSafepoint(code_offset : Int, live_refs : Array[Int], metadata : Int64) -> GcSafepointpub(all) struct HostcallImportTrampolineCode {
code : Array[Int]
func_addr_fixups : Array[FuncAddrFixup]
}pub(all) struct HotThreshold {
warm_threshold : Int
hot_threshold : Int
}pub struct JITFunctionDebug {
ir : String
machv_before_regalloc : String
machv_after_regalloc : String
machine_code : String
}fn JITFunctionDebug::JITFunctionDebug(ir : String, machv_before_regalloc : String, machv_after_regalloc : String, machine_code : String) -> JITFunctionDebugtype JITRuntimeimpl Show for JITRuntimefn JITRuntime::register(self : JITRuntime, func_idx : Int, func : CompiledFunction) -> Result[Int, String]pub(all) struct JitIntegrationPlan {
entry_symbol : String
target : EmitTarget
native_glue : Array[NativeGlueBinding]
object : MachineCode
}pub(all) struct LinkedCode {
code : Array[Int]
frame_size : Int
runtime_relocations : Array[ResolvedRuntimeRelocation]
func_addr_fixups : Array[FuncAddrFixup]
call_fixups : Array[CallFixup]
gc_safepoints : Array[GcSafepoint]
gc_stackmap_blob : Bytes
} derive(Debug)pub(all) struct MemoryDescriptorLayout {
base_offset : Int
current_length_offset : Int
}pub struct MemoryInfo {
ptr : Int64
size : Int64
max_pages : Int?
}type MemoryManagerimpl Show for MemoryManagerfn MemoryManager::write_code(self : MemoryManager, code : MachineCode) -> Result[(ExecutableRegion, Int), String]pub(all) struct NativeGlueBinding {
kind : NativeGlueKind
symbol : String
sources : Array[String]
} derive(Eq, Debug)type NativeJITContextfn NativeJITContext::alloc_guarded_memory(self : NativeJITContext, initial_pages : Int, max_pages : Int?) -> Int64fn NativeJITContext::call_trampoline(self : NativeJITContext, trampoline_ptr : Int64, func_ptr : Int64, values_vec : FixedArray[Int64], values_len : Int, use_stack_switch : Bool) -> Intfn NativeJITContext::set_cancellation_callback(self : NativeJITContext, callback : () -> Bool) -> Unitfn NativeJITContext::set_indirect(self : NativeJITContext, table_idx : Int, func_idx : Int, type_idx : Int) -> Unitfn NativeJITContext::set_memory_pointers(self : NativeJITContext, memories : Array[MemoryInfo]) -> Unitfn NativeJITContext::set_table_pointers(self : NativeJITContext, jit_tables : Array[JITTable?]) -> Unitpub(all) struct Profiler {
counter : CallCounter
threshold : HotThreshold
hot_functions : HashSet[Int]
pending_compilation : HashSet[Int]
compiled_functions : HashSet[Int]
}fn RuntimeSymbolResolver::add_symbol(self : RuntimeSymbolResolver, name : String, address : Int64) -> Unitfn RuntimeSymbolResolver::add_symbol_fixup(self : RuntimeSymbolResolver, name : String, address : Int64, fixup_idx : Int) -> Unitfn RuntimeSymbolResolver::resolve_symbol(self : RuntimeSymbolResolver, name : String) -> RuntimeSymbol?pub(all) struct TieredConfig {
baseline_threshold : Int
optimize_threshold : Int
synchronous : Bool
max_concurrent : Int
}pub struct TrapDetails {
signal : Int
pc : Int64
lr : Int64
fp : Int64
frame_lr : Int64
fault_addr : Int64
brk_imm : Int
func_idx : Int
x0 : Int64
x1 : Int64
x2 : Int64
x3 : Int64
x6 : Int64
x7 : Int64
x8 : Int64
x9 : Int64
x10 : Int64
x11 : Int64
x15 : Int64
}pub(all) struct TrapReport {
trap_kind : String
message : String
signal : Int
signal_name : String
pc : Int64
lr : Int64
fp : Int64
frame_lr : Int64
fault_addr : Int64
brk_imm : Int
wasm_func_idx : Int?
wasm_func_name : String?
wasm_offset : Int64?
wasm_frames : Array[WasmTrapFrame]
host_frames : Array[String]
dump_path : String?
}pub(all) struct VMContextLayout {
memory0_offset : Int
memory0_base_offset : Int
memory0_size_offset : Int
func_table_offset : Int
table0_base_offset : Int
table0_elements_offset : Int
globals_offset : Int
tables_offset : Int
table_count_offset : Int
func_count_offset : Int
table_sizes_offset : Int
table_max_sizes_offset : Int
memories_offset : Int
memory_count_offset : Int
debug_current_func_idx_offset : Int
gc_heap_ptr_offset : Int
gc_heap_limit_offset : Int
gc_heap_offset : Int
pointer_stride : Int
global_value_stride : Int
table_entry_value_offset : Int
table_entry_stride : Int
func_table_entry_stride : Int
}pub(all) struct WasmTrapFrame {
pc : Int64
func_idx : Int
func_name : String
wasm_offset : Int64
}fn alloc_guarded_memory_desc(initial_pages : Int, max_pages : Int?) -> Int64fn alloc_memory(size : Int64) -> Int64fn alloc_memory_desc(size_bytes : Int64, max_pages : Int?, is_memory64? : Bool, page_size_log2? : Int, is_shared? : Bool) -> Int64fn build_cwasm_entry_from_code(func_idx : Int, name : String, code : Array[Int], frame_size : Int, entry_offset : Int, num_params : Int, num_results : Int, func_addr_fixups? : Array[FuncAddrFixup], call_fixups? : Array[CallFixup], gc_safepoint_offsets? : Array[Int], gc_safepoint_root_counts? : Array[Int], gc_safepoint_root_indices? : Array[Array[Int]], gc_safepoints? : Array[GcSafepoint], gc_stackmap_blob? : Bytes) -> CompiledEntryfn build_entry_trampoline_for_target(param_types : Array[ValueType], result_types : Array[ValueType], target : TargetArch) -> Array[Int] raise HostcallImportTrampolineErrorfn build_gc_stackmap_blob_for_safepoints(safepoints : Array[GcSafepoint], root_counts : Array[Int], explicit_blob? : Bytes) -> Bytesfn build_gc_stackmap_blob_v2(safepoints : Array[GcSafepoint], default_root_counts : Array[Int]) -> Bytesfn build_hostcall_import_trampoline_for_target(param_types : Array[ValueType], result_types : Array[ValueType], host_func_addr : Int, target : TargetArch) -> HostcallImportTrampolineCode raise HostcallImportTrampolineErrorfn c_jit_read_i64(addr : Int64) -> Int64fn c_jit_write_i64(addr : Int64, value : Int64) -> Unitfn c_jit_write_u32(addr : Int64, value : Int) -> Unitfn decode_heap_ref(encoded : Int64) -> Intfn emit_entry_trampoline(param_types : Array[Int], result_types : Array[Int], call_conv_layout : CallConventionLayout, isa? : ISA) -> MachineCodefn emit_hostcall_import_trampoline(param_types : Array[ValueType], result_types : Array[ValueType], host_func_addr : Int, hostcall_symbol : ExternalName, call_conv_layout : CallConventionLayout, isa? : ISA) -> MachineCodefn encode_heap_ref(heap_idx : Int) -> Int64fn encode_i31(value : Int) -> Int64fn encode_x64_call_rel32_disp(pc : Int64, target_ptr : Int64) -> Int?fn exception_runtime_fixup_idx(ordinal : Int) -> Intfn gc_begin_frame(ctx_ptr : Int64, frame_id : Int64) -> Unitfn gc_clear_heap(ctx_ptr : Int64) -> Unitfn gc_debug_set_fail_alloc(fail_at : Int, fail_every? : Int) -> Unitfn gc_end_frame(ctx_ptr : Int64) -> Unitfn gc_runtime_fixup_idx(ordinal : Int) -> Intfn gc_safepoint_metadata_to_root_count(metadata : Int64) -> Intfn gc_set_func_safepoints(ctx_ptr : Int64, func_idx : Int, safepoints : Array[GcSafepoint], stackmap_blob : Bytes) -> Boolfn gc_set_safepoint_table(ctx_ptr : Int64, table_ptr : Int64) -> Unitfn get_gc_array_copy_ptr() -> Int64fn get_gc_array_fill_ptr() -> Int64fn get_gc_array_get_ptr() -> Int64fn get_gc_array_len_ptr() -> Int64fn get_gc_array_new_ptr() -> Int64fn get_gc_array_set_ptr() -> Int64fn get_gc_ref_cast_ptr() -> Int64fn get_gc_ref_test_ptr() -> Int64fn get_gc_struct_get_ptr() -> Int64fn get_gc_struct_new_ptr() -> Int64fn get_gc_struct_set_ptr() -> Int64fn get_gc_type_check_subtype_ptr() -> Int64fn get_hostcall_func_addr() -> Intfn get_hostcall_num_arg_slots() -> Intfn get_hostcall_num_result_slots() -> Intfn get_hostcall_values_ptr() -> Int64fn get_import_trampoline(module_name : String, field_name : String) -> Int64?fn install_direct_call_stubs_for_target(target : TargetArch) -> DirectCallStubSet raise DirectCallStubInstallErrorfn is_jit_supported_module(module_name : String) -> Boolfn jit_runtime_fixup_idx(ordinal : Int) -> Intfn link_code_object(object : MachineCode, resolver : RuntimeSymbolResolver) -> LinkedCode raise LinkErrorfn link_machine_code(object : MachineCode, resolver : RuntimeSymbolResolver) -> LinkedCode raise LinkErrorfn memory_init(mem_ptr : Int64, offset : Int64, data : Bytes) -> Boolfn memory_read(mem_ptr : Int64, offset : Int64, size : Int) -> Bytesfn patch_aarch64_call_veneer_target(exec_ptr : Int64, fixup : CallFixup, target_ptr : Int64) -> Unitfn patch_aarch64_func_addr_fixup(exec_ptr : Int64, fixup : FuncAddrFixup, target_ptr : Int64) -> Unitfn patch_aarch64_func_addr_fixup_parts(exec_ptr : Int64, offset : Int, reg : Int, target_ptr : Int64) -> Unitfn patch_aarch64_func_addr_fixup_raw(exec_ptr : Int64, offset : Int, reg : Int, func_idx : Int, func_table_ptr : Int64) -> Unitfn patch_aarch64_func_addr_fixups(exec_ptr : Int64, fixups : Array[FuncAddrFixup], func_table_ptr : Int64) -> Unitfn patch_aarch64_load_imm64_fixed(exec_ptr : Int64, offset : Int, reg : Int, imm : Int64) -> Unitfn patch_call_fixups_for_target(target : TargetArch, exec_ptr : Int64, fixups : Array[CallFixup], func_table_ptr : Int64, direct_call_targets : Map[Int, Int64]) -> Unitfn patch_func_addr_fixup_raw_for_target(target : TargetArch, exec_ptr : Int64, offset : Int, reg : Int, func_idx : Int, func_table_ptr : Int64) -> Unitfn patch_func_addr_fixups_for_target(target : TargetArch, exec_ptr : Int64, fixups : Array[FuncAddrFixup], func_table_ptr : Int64) -> Unitfn patch_x64_func_addr_fixup_parts(exec_ptr : Int64, offset : Int, _reg : Int, target_ptr : Int64) -> Unitfn patch_x64_func_addr_fixup_raw(exec_ptr : Int64, offset : Int, reg : Int, func_idx : Int, func_table_ptr : Int64) -> Unitfn patch_x64_func_addr_fixups(exec_ptr : Int64, fixups : Array[FuncAddrFixup], func_table_ptr : Int64) -> Unitfn plan_entry_trampoline_for_target(param_types : Array[ValueType], result_types : Array[ValueType], target : EmitTarget) -> JitIntegrationPlan raise JitPipelineErrorfn plan_hostcall_import_trampoline_layout(param_types : Array[ValueType], result_types : Array[ValueType], max_int_regs : Int, max_float_regs : Int) -> HostcallImportTrampolineLayoutfn plan_integration_for_target(func : Function, machv_func : Function, regalloc_output : Output, target : EmitTarget) -> JitIntegrationPlanfn plan_wasm_body_milkir_integration_for_target(func : Function, target : EmitTarget) -> JitIntegrationPlanfn required_context_function_count(precompiled : PrecompiledModule, func_signature_count : Int) -> Intfn resolve_call_fixup_target(func_idx : Int, func_table_ptr : Int64, direct_call_targets : Map[Int, Int64]) -> Int64?fn resolve_func_addr_fixup_target(func_idx : Int, func_table_ptr : Int64) -> Int64?fn resolve_import_function(external_imports : Map[String, Map[String, Int64]], module_name : String, field_name : String) -> ImportFunctionResolutionfn resolve_runtime_func_fixup_idx(idx : Int) -> Int64?fn set_wasi_stdin_callback(ctx_ptr : Int64, callback : () -> Bytes) -> Unitfn wasm_trap_payload(reason : String) -> Int