Skip to content

Commit a7050e7

Browse files
committed
Pull side-trace codegen-specific stuff out of the JIT module.
This commit is, again, a bit of a hack, but it still makes things a bit better than before. In essence, before this commit JIT modules contained `yksmp::Location`s for "normal" traces and `VarLocation`s for side traces. The former are codegen agnostic: the latter are codegen specific. This commit hoiks the `VarLocation`s out of the JIT mod and puts them in `TraceKind::Sidetrace`. Now that would end up having us add a `Register` type parameter everywhere, which is too much churn, so for now `TraceKind::Sidetrace` stores an `Arc<SidetraceInfo>` i.e. we store it as a trait object. We then have to downcast to `YkSideTraceInfo` in lots of places. This is pretty evil, because we're using dynamic typing where we should be using static typing. However, overall, this is the lesser of the evils. By the end of this commit, it's clearer (even if not perfectly so) the relationship between trace inputs and side-trace outputs. We can do better in the future, and maybe we'll want to do so, but this does feel like a nudge in the right direction.
1 parent b411c0e commit a7050e7

File tree

9 files changed

+160
-131
lines changed

9 files changed

+160
-131
lines changed

ykrt/src/compile/jitc_yk/codegen/x64/lsregalloc.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,9 +1029,7 @@ impl LSRegAlloc<'_> {
10291029
RegConstraint::Output
10301030
| RegConstraint::OutputCanBeSameAsInput(_)
10311031
| RegConstraint::InputOutput(_) => {
1032-
if let Some(reg_alloc::Register::FP(reg)) =
1033-
self.rev_an.reg_hints[usize::from(iidx)]
1034-
{
1032+
if let Some(Register::FP(reg)) = self.rev_an.reg_hints[usize::from(iidx)] {
10351033
if !avoid.is_set(reg) {
10361034
*cnstr = match cnstr {
10371035
RegConstraint::Output => RegConstraint::OutputFromReg(reg),

ykrt/src/compile/jitc_yk/codegen/x64/mod.rs

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ use dynasmrt::{
5353
use indexmap::IndexMap;
5454
use parking_lot::Mutex;
5555
use std::{
56+
assert_matches::debug_assert_matches,
5657
cell::Cell,
5758
collections::HashMap,
5859
error::Error,
@@ -643,7 +644,7 @@ impl<'a> Assemble<'a> {
643644
}
644645
jit_ir::Inst::TraceBodyStart => self.cg_body_start(),
645646
jit_ir::Inst::TraceBodyEnd => self.cg_body_end(iidx),
646-
jit_ir::Inst::SidetraceEnd => self.cg_sidetrace_end(iidx, self.m.root_jump_addr()),
647+
jit_ir::Inst::SidetraceEnd => self.cg_sidetrace_end(iidx),
647648
jit_ir::Inst::SExt(i) => self.cg_sext(iidx, i),
648649
jit_ir::Inst::ZExt(i) => self.cg_zext(iidx, i),
649650
jit_ir::Inst::BitCast(i) => self.cg_bitcast(iidx, i),
@@ -1951,9 +1952,17 @@ impl<'a> Assemble<'a> {
19511952
/// * `tgt_vars` - The target locations. If `None` use `self.loop_start_locs` instead.
19521953
fn write_jump_vars(&mut self, iidx: InstIdx) {
19531954
let (tgt_vars, src_ops) = match self.m.tracekind() {
1954-
TraceKind::HeaderOnly => (self.header_start_locs.as_slice(), self.m.trace_header_end()),
1955-
TraceKind::HeaderAndBody => (self.body_start_locs.as_slice(), self.m.trace_body_end()),
1956-
TraceKind::Sidetrace => (self.m.root_entry_vars(), self.m.trace_header_end()),
1955+
TraceKind::HeaderOnly => (self.header_start_locs.clone(), self.m.trace_header_end()),
1956+
TraceKind::HeaderAndBody => (self.body_start_locs.clone(), self.m.trace_body_end()),
1957+
TraceKind::Sidetrace(sti) => (
1958+
Arc::clone(sti)
1959+
.as_any()
1960+
.downcast::<YkSideTraceInfo<Register>>()
1961+
.unwrap()
1962+
.entry_vars
1963+
.clone(),
1964+
self.m.trace_header_end(),
1965+
),
19571966
};
19581967
// If we pass in `None` use `self.loop_start_locs` instead. We need to do this since we
19591968
// can't pass in `&self.loop_start_locs` directly due to borrowing restrictions.
@@ -2046,7 +2055,7 @@ impl<'a> Assemble<'a> {
20462055
}
20472056

20482057
fn cg_body_end(&mut self, iidx: InstIdx) {
2049-
debug_assert_eq!(self.m.tracekind(), TraceKind::HeaderAndBody);
2058+
debug_assert_matches!(self.m.tracekind(), TraceKind::HeaderAndBody);
20502059
// Loop the JITted code if the `tloop_start` label is present (not relevant for IR created
20512060
// by a test or a side-trace).
20522061
let label = StaticLabel::global("tloop_start");
@@ -2074,21 +2083,29 @@ impl<'a> Assemble<'a> {
20742083
}
20752084
}
20762085

2077-
fn cg_sidetrace_end(&mut self, iidx: InstIdx, addr: *const libc::c_void) {
2078-
debug_assert_eq!(self.m.tracekind(), TraceKind::Sidetrace);
2079-
// The end of a side-trace. Map live variables of this side-trace to the entry variables of
2080-
// the root parent trace, then jump to it.
2081-
self.write_jump_vars(iidx);
2082-
self.ra.align_stack(SYSV_CALL_STACK_ALIGN);
2086+
fn cg_sidetrace_end(&mut self, iidx: InstIdx) {
2087+
match self.m.tracekind() {
2088+
TraceKind::Sidetrace(sti) => {
2089+
let sti = Arc::clone(sti)
2090+
.as_any()
2091+
.downcast::<YkSideTraceInfo<Register>>()
2092+
.unwrap();
2093+
// The end of a side-trace. Map live variables of this side-trace to the entry variables of
2094+
// the root parent trace, then jump to it.
2095+
self.write_jump_vars(iidx);
2096+
self.ra.align_stack(SYSV_CALL_STACK_ALIGN);
20832097

2084-
dynasm!(self.asm
2085-
// Reset rsp to the root trace's frame.
2086-
; mov rsp, rbp
2087-
; sub rsp, i32::try_from(self.root_offset.unwrap()).unwrap()
2088-
; mov rdi, QWORD addr as i64
2089-
// We can safely use RDI here, since the root trace won't expect live variables in this
2090-
// register since it's being used as an argument to the control point.
2091-
; jmp rdi);
2098+
dynasm!(self.asm
2099+
// Reset rsp to the root trace's frame.
2100+
; mov rsp, rbp
2101+
; sub rsp, i32::try_from(sti.root_offset()).unwrap()
2102+
; mov rdi, QWORD sti.root_addr() as i64
2103+
// We can safely use RDI here, since the root trace won't expect live variables in this
2104+
// register since it's being used as an argument to the control point.
2105+
; jmp rdi);
2106+
}
2107+
TraceKind::HeaderOnly | TraceKind::HeaderAndBody => panic!(),
2108+
}
20922109
}
20932110

20942111
fn cg_header_start(&mut self) {
@@ -2110,7 +2127,7 @@ impl<'a> Assemble<'a> {
21102127
TraceKind::HeaderAndBody => {
21112128
dynasm!(self.asm; ->reentry:);
21122129
}
2113-
TraceKind::Sidetrace => todo!(),
2130+
TraceKind::Sidetrace(_) => todo!(),
21142131
}
21152132
self.prologue_offset = self.asm.offset();
21162133
}
@@ -2172,12 +2189,12 @@ impl<'a> Assemble<'a> {
21722189
}
21732190
}
21742191
}
2175-
TraceKind::Sidetrace => todo!(),
2192+
TraceKind::Sidetrace(_) => panic!(),
21762193
}
21772194
}
21782195

21792196
fn cg_body_start(&mut self) {
2180-
debug_assert_eq!(self.m.tracekind(), TraceKind::HeaderAndBody);
2197+
debug_assert_matches!(self.m.tracekind(), &TraceKind::HeaderAndBody);
21812198
debug_assert_eq!(self.body_start_locs.len(), 0);
21822199
// Remember the locations of the live variables at the beginning of the trace loop. When we
21832200
// loop back around here we need to write the live variables back into these same

ykrt/src/compile/jitc_yk/codegen/x64/rev_analyse.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ use crate::compile::jitc_yk::{
1919
BinOp, BinOpInst, DirectCallInst, DynPtrAddInst, ICmpInst, Inst, InstIdx, LoadInst, Module,
2020
Operand, PtrAddInst, SExtInst, SelectInst, StoreInst, TraceKind, TruncInst, Ty, ZExtInst,
2121
},
22+
YkSideTraceInfo,
2223
};
2324
use dynasmrt::x64::Rq;
25+
use std::sync::Arc;
2426
use vob::Vob;
2527

2628
pub(crate) struct RevAnalyse<'a> {
@@ -80,8 +82,12 @@ impl<'a> RevAnalyse<'a> {
8082
// We don't care where the register allocator ends at the end of the header, so we
8183
// don't propagate backwards from `TraceHeaderEnd`.
8284
}
83-
TraceKind::Sidetrace => {
84-
let vlocs = self.m.root_entry_vars();
85+
TraceKind::Sidetrace(sti) => {
86+
let sti = Arc::clone(sti)
87+
.as_any()
88+
.downcast::<YkSideTraceInfo<Register>>()
89+
.unwrap();
90+
let vlocs = &sti.entry_vars;
8591
// Side-traces don't have a trace body since we don't apply loop peeling and thus use
8692
// `trace_header_end` to store the jump variables.
8793
debug_assert_eq!(vlocs.len(), self.m.trace_header_end().len());
@@ -97,7 +103,7 @@ impl<'a> RevAnalyse<'a> {
97103
// ...and then we perform the rest of the reverse analysis.
98104
let mut iter = self.m.iter_skipping_insts().rev();
99105
match self.m.tracekind() {
100-
TraceKind::HeaderOnly | TraceKind::Sidetrace => {
106+
TraceKind::HeaderOnly | TraceKind::Sidetrace(_) => {
101107
for (iidx, inst) in self.m.iter_skipping_insts().rev() {
102108
self.analyse(iidx, inst);
103109
}

ykrt/src/compile/jitc_yk/jit_ir/mod.rs

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,17 @@ mod parser;
9696
#[cfg(any(debug_assertions, test))]
9797
mod well_formed;
9898

99+
use super::aot_ir;
99100
#[cfg(debug_assertions)]
100101
use super::int_signs::Truncate;
101-
use super::{aot_ir, VarLocation};
102-
use crate::compile::CompilationError;
102+
use crate::compile::{CompilationError, SideTraceInfo};
103103
use indexmap::IndexSet;
104104
use std::{
105105
ffi::{c_void, CString},
106106
fmt,
107107
hash::Hash,
108108
mem,
109+
sync::Arc,
109110
};
110111
use strum::{EnumCount, EnumDiscriminants};
111112
#[cfg(not(test))]
@@ -115,15 +116,15 @@ use ykaddr::addr::symbol_to_ptr;
115116
pub(crate) use super::aot_ir::{BinOp, FloatPredicate, FloatTy, Predicate};
116117

117118
/// What kind of trace does this module represent?
118-
#[derive(Copy, Clone, Debug, PartialEq)]
119+
#[derive(Clone, Debug)]
119120
pub(crate) enum TraceKind {
120121
/// A trace which contains only a header: the trace must loop back to the very start every
121122
/// time.
122123
HeaderOnly,
123124
/// A trace with a header and a body: the trace must loop back to the start of the body.
124125
HeaderAndBody,
125126
/// A sidetrace: the trace must loop back to the root of the trace tree.
126-
Sidetrace,
127+
Sidetrace(Arc<dyn SideTraceInfo>),
127128
}
128129

129130
/// The `Module` is the top-level container for JIT IR.
@@ -180,8 +181,6 @@ pub(crate) struct Module {
180181
guard_info: Vec<GuardInfo>,
181182
/// Indirect calls.
182183
indirect_calls: Vec<IndirectCallInst>,
183-
/// Live variables at the beginning of the root trace.
184-
root_entry_vars: Vec<VarLocation>,
185184
/// Live variables at the beginning of the trace body.
186185
pub(crate) trace_body_start: Vec<PackedOperand>,
187186
/// The ordered sequence of operands at the end of the trace body: there will be one per
@@ -215,15 +214,15 @@ impl Module {
215214

216215
/// Returns this module's current [TraceKind]. Note: this can change as a result of calling
217216
/// [Self::set_tracekind]!
218-
pub(crate) fn tracekind(&self) -> TraceKind {
219-
self.tracekind
217+
pub(crate) fn tracekind(&self) -> &TraceKind {
218+
&self.tracekind
220219
}
221220

222221
/// Returns this module's current [TraceKind]. Currently the only transition allowed is from
223222
/// [TraceKind::HeaderOnly] to [TraceKind::HeaderAndBody].
224223
pub(crate) fn set_tracekind(&mut self, tracekind: TraceKind) {
225-
match (self.tracekind, tracekind) {
226-
(TraceKind::HeaderOnly, TraceKind::HeaderAndBody) => (),
224+
match (&self.tracekind, &tracekind) {
225+
(&TraceKind::HeaderOnly, &TraceKind::HeaderAndBody) => (),
227226
(from, to) => panic!("Can't transition from a {from:?} trace to a {to:?} trace"),
228227
}
229228
self.tracekind = tracekind;
@@ -304,7 +303,6 @@ impl Module {
304303
global_decls: IndexSet::new(),
305304
guard_info: Vec::new(),
306305
indirect_calls: Vec::new(),
307-
root_entry_vars: Vec::new(),
308306
trace_body_start: Vec::new(),
309307
trace_body_end: Vec::new(),
310308
trace_header_start: Vec::new(),
@@ -642,37 +640,14 @@ impl Module {
642640
self.trace_header_start.push(PackedOperand::new(&op));
643641
}
644642

645-
/// Store the entry live variables of the root traces so we can copy this side-trace's live
646-
/// variables to the right place before jumping back to the root trace.
647-
pub(crate) fn set_root_entry_vars(&mut self, entry_vars: &[VarLocation]) {
648-
self.root_entry_vars.extend_from_slice(entry_vars);
649-
}
650-
651643
/// Return the loop jump operands.
652644
pub(crate) fn trace_body_end(&self) -> &[PackedOperand] {
653645
&self.trace_body_end
654646
}
655647

656-
/// Get the entry live variables of the root trace.
657-
pub(crate) fn root_entry_vars(&self) -> &[VarLocation] {
658-
&self.root_entry_vars
659-
}
660-
661648
pub(crate) fn push_header_end_var(&mut self, op: Operand) {
662649
self.trace_header_end.push(PackedOperand::new(&op));
663650
}
664-
665-
/// Get the address of the root trace. This is where we need jump to at the end of a
666-
/// side-trace.
667-
pub(crate) fn root_jump_addr(&self) -> *const libc::c_void {
668-
self.root_jump_ptr
669-
}
670-
671-
/// Set the entry address of the root trace. This is where we need jump to at the end of a
672-
/// side-trace.
673-
pub(crate) fn set_root_jump_addr(&mut self, ptr: *const libc::c_void) {
674-
self.root_jump_ptr = ptr;
675-
}
676651
}
677652

678653
impl fmt::Display for Module {

ykrt/src/compile/jitc_yk/jit_ir/well_formed.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,17 @@ use super::{BinOp, BinOpInst, Const, GuardInst, Inst, Module, Operand, Ty};
2828

2929
impl Module {
3030
pub(crate) fn assert_well_formed(&self) {
31-
if !self.root_entry_vars.is_empty() {
32-
if self.root_entry_vars.len() != self.trace_header_end.len() {
33-
panic!("Loop start/end variables have different lengths.");
31+
match self.tracekind() {
32+
super::TraceKind::HeaderOnly | super::TraceKind::HeaderAndBody => {
33+
if self.trace_header_start.len() != self.trace_header_end.len() {
34+
panic!(
35+
"Loop start ({}) / end ({}) variables have different length.",
36+
self.trace_header_start.len(),
37+
self.trace_header_end.len()
38+
);
39+
}
3440
}
35-
} else if self.trace_header_start.len() != self.trace_header_end.len() {
36-
panic!("Loop start/end variables have different lengths.");
41+
super::TraceKind::Sidetrace(_) => (),
3742
}
3843

3944
let mut last_inst = None;

0 commit comments

Comments
 (0)