From 4efafa4c4f7cc37fb915069291faa6b464883ffa Mon Sep 17 00:00:00 2001 From: Lukas Diekmann Date: Thu, 17 Oct 2024 14:41:24 +0100 Subject: [PATCH 1/2] Improve some docs. --- ykrt/src/compile/jitc_yk/codegen/mod.rs | 2 +- ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs | 25 ++++++++++++++----- ykrt/src/compile/jitc_yk/codegen/x64/mod.rs | 8 +++--- ykrt/src/compile/jitc_yk/mod.rs | 7 ++++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/ykrt/src/compile/jitc_yk/codegen/mod.rs b/ykrt/src/compile/jitc_yk/codegen/mod.rs index 2f5f7c5de..81b6de1ac 100644 --- a/ykrt/src/compile/jitc_yk/codegen/mod.rs +++ b/ykrt/src/compile/jitc_yk/codegen/mod.rs @@ -23,7 +23,7 @@ pub(crate) trait CodeGen: Send + Sync { /// # Arguments /// /// * `sp_offset` - Stack pointer offset from the base pointer of the interpreter frame as - /// defined in [YkSideTraceInfo::sp_offset]. + /// defined in [super::YkSideTraceInfo::sp_offset]. fn codegen( &self, m: Module, diff --git a/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs b/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs index 319c35e69..a08aea60c 100644 --- a/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs +++ b/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs @@ -26,8 +26,12 @@ const RECOVER_REG: [usize; 31] = [ /// from zero). This is used to allocate arrays whose indices need to be the DWARF register number. const REGISTER_NUM: usize = RECOVER_REG.len() + 2; -/// When a guard fails, check if we have compiled a side-trace for this guard and if so, return -/// it's address. Otherwise return NULL, indicating that we need to deoptimise. +/// When a guard fails, checks if there exists a compiled side-trace for this guard and if so, +/// returns it's address. Otherwise returns a null pointer, indicating that we need to deoptimise. +/// +/// # Arguments +/// +/// * gidx - The [GuardIdx] of the failing guard. #[no_mangle] pub(crate) extern "C" fn __yk_guardcheck(gidx: u64) -> *const libc::c_void { let gidx = GuardIdx::from(usize::try_from(gidx).unwrap()); @@ -61,6 +65,7 @@ pub(crate) extern "C" fn __yk_guardcheck(gidx: u64) -> *const libc::c_void { std::ptr::null() } +/// Informs the meta-tracer that we have looped back from a side-trace into the root trace. pub(crate) extern "C" fn __yk_reenter_jit() { // Get the root trace and set it as the new running trace. let (_, root) = MTThread::with(|mtt| mtt.running_trace()); @@ -77,10 +82,15 @@ pub(crate) extern "C" fn __yk_reenter_jit() { } /// Deoptimise back to the interpreter. This function is called from a failing guard (see -/// `x86_64/mod.rs`). The arguments are: `frameaddr` is the RBP value for main interpreter loop -/// (and also the JIT since the trace executes on the same frame); `gidx` the ID of the failing -/// guard; and `gp_regs` is a pointer to the saved values of the 16 general purpose registers in -/// the same order as [lsregalloc::GP_REGS]. +/// [super::Assemble::codegen]). +/// +/// # Arguments +/// +/// * `frameaddr` - the RBP value for main interpreter loop (and also the JIT since the trace +/// executes on the same frame) +/// * `gidx` - the [GuardIdx] of the failing guard +/// * `gp_regs` - a pointer to the saved values of the 16 general purpose registers in the same +/// order as [crate::compile::jitc_yk::codegen::x64::lsregalloc::GP_REGS] #[no_mangle] pub(crate) extern "C" fn __yk_deopt( frameaddr: *const c_void, @@ -321,6 +331,9 @@ pub(crate) extern "C" fn __yk_deopt( unsafe { __replace_stack(newframedst as *mut c_void, newstack, memsize) }; } +/// Writes the stack frames that we recreated in [__yk_deopt] onto the current stack, overwriting +/// the stack frames of any running traces in the process. This deoptimises trace execution after +/// which we can safely return to the normal execution of the interpreter. #[cfg(target_arch = "x86_64")] #[naked] #[no_mangle] diff --git a/ykrt/src/compile/jitc_yk/codegen/x64/mod.rs b/ykrt/src/compile/jitc_yk/codegen/x64/mod.rs index 4c36845e6..90f36bf67 100644 --- a/ykrt/src/compile/jitc_yk/codegen/x64/mod.rs +++ b/ykrt/src/compile/jitc_yk/codegen/x64/mod.rs @@ -834,6 +834,8 @@ impl<'a> Assemble<'a> { } } + /// Codegen a [jit_ir::LoadTraceInputInst]. This only informs the register allocator about the + /// locations of live variables without generating any actual machine code. fn cg_loadtraceinput(&mut self, iidx: jit_ir::InstIdx, inst: &jit_ir::LoadTraceInputInst) { let m = match &self.m.tilocs()[usize::try_from(inst.locidx()).unwrap()] { yksmp::Location::Register(0, ..) => { @@ -1335,10 +1337,8 @@ impl<'a> Assemble<'a> { } fn cg_traceloopjump(&mut self) { - // Loop the JITted code if the `tloop_start` label is present. If not we are dealing with - // IR created by a test or a side-trace (the latter likely needs something similar to loop - // jumps, but instead of jumping within the same trace we want it to jump to the outer-most - // parent trace). + // Loop the JITted code if the `tloop_start` label is present (not relevant for IR created + // by a test or a side-trace). let label = StaticLabel::global("tloop_start"); match self.asm.labels().resolve_static(&label) { Ok(_) => { diff --git a/ykrt/src/compile/jitc_yk/mod.rs b/ykrt/src/compile/jitc_yk/mod.rs index 4726c36a3..0243aad04 100644 --- a/ykrt/src/compile/jitc_yk/mod.rs +++ b/ykrt/src/compile/jitc_yk/mod.rs @@ -46,17 +46,20 @@ struct RootTracePtr(*const libc::c_void); unsafe impl Send for RootTracePtr {} unsafe impl Sync for RootTracePtr {} +/// Contains information required for side-tracing. struct YkSideTraceInfo { /// The AOT IR block the failing guard originated from. bid: aot_ir::BBlockId, + /// Inlined calls tracked by [trace_builder] during processing of a trace. Required for + /// side-tracing in order setup a new [trace_builder] and process a side-trace. callframes: Vec, /// Mapping of AOT variables to their current location. Used to pass variables from a parent /// trace into a side-trace. lives: Vec<(aot_ir::InstID, Location)>, - /// The address of the parent trace. This is where the side-trace needs to jump back to after it + /// The address of the root trace. This is where the side-trace needs to jump back to after it /// finished its execution. root_addr: RootTracePtr, - /// The live variables at the entry point of the parent trace. + /// The live variables at the entry point of the root trace. entry_vars: Vec, /// Stack pointer offset from the base pointer of the interpreter frame including the /// interpreter frame itself and all parent traces. Since all traces execute in the interpreter From 51dc80fa12a15cad0956aff9ca6b3a307a62e255 Mon Sep 17 00:00:00 2001 From: Lukas Diekmann Date: Thu, 17 Oct 2024 14:42:21 +0100 Subject: [PATCH 2/2] Rename one and un-nomangle another function. --- ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs | 5 ++--- ykrt/src/mt.rs | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs b/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs index a08aea60c..230cea162 100644 --- a/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs +++ b/ykrt/src/compile/jitc_yk/codegen/x64/deopt.rs @@ -328,7 +328,7 @@ pub(crate) extern "C" fn __yk_deopt( drop(ctr); // Now overwrite the existing stack with our newly recreated one. - unsafe { __replace_stack(newframedst as *mut c_void, newstack, memsize) }; + unsafe { replace_stack(newframedst as *mut c_void, newstack, memsize) }; } /// Writes the stack frames that we recreated in [__yk_deopt] onto the current stack, overwriting @@ -336,8 +336,7 @@ pub(crate) extern "C" fn __yk_deopt( /// which we can safely return to the normal execution of the interpreter. #[cfg(target_arch = "x86_64")] #[naked] -#[no_mangle] -unsafe extern "C" fn __replace_stack(dst: *mut c_void, src: *const c_void, size: usize) -> ! { +unsafe extern "C" fn replace_stack(dst: *mut c_void, src: *const c_void, size: usize) -> ! { std::arch::naked_asm!( // Reset RSP to the end of the control point frame (this doesn't include the // return address which will thus be overwritten in the process) diff --git a/ykrt/src/mt.rs b/ykrt/src/mt.rs index c66c5a01c..4e98fa225 100644 --- a/ykrt/src/mt.rs +++ b/ykrt/src/mt.rs @@ -366,7 +366,7 @@ impl MT { // FIXME: Calling this function overwrites the current (Rust) function frame, // rather than unwinding it. https://github.com/ykjit/yk/issues/778. - unsafe { exec_trace(frameaddr, rsp, trace_addr) }; + unsafe { __yk_exec_trace(frameaddr, rsp, trace_addr) }; } TransitionControlPoint::StartTracing(hl) => { self.log.log(Verbosity::JITEvent, "start-tracing"); @@ -692,7 +692,7 @@ impl MT { #[cfg(target_arch = "x86_64")] #[naked] #[no_mangle] -unsafe extern "C" fn exec_trace( +unsafe extern "C" fn __yk_exec_trace( frameaddr: *const c_void, rsp: *const c_void, trace: *const c_void,