Skip to content

Commit 8da752c

Browse files
committed
ZJIT: Box lir::CCall data
Shrink `lir::Insn` from 144 to 80 bytes.
1 parent 4a396c1 commit 8da752c

3 files changed

Lines changed: 51 additions & 33 deletions

File tree

zjit/src/backend/arm64/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1431,7 +1431,8 @@ impl Assembler {
14311431
// First operand is popped from the lower stack address
14321432
ldp_post(cb, first_pop, second_pop, A64Opnd::new_mem(64, C_SP_REG, C_SP_STEP));
14331433
},
1434-
Insn::CCall { fptr, .. } => {
1434+
Insn::CCall { data, .. } => {
1435+
let fptr = &data.fptr;
14351436
match fptr {
14361437
Opnd::UImm(fptr) => {
14371438
// The offset to the call target in bytes

zjit/src/backend/lir.rs

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,25 @@ impl From<CodePtr> for Target {
636636

637637
type PosMarkerFn = Rc<dyn Fn(CodePtr, &CodeBlock)>;
638638

639+
/// Cold fields of `Insn::CCall`, boxed to keep `Insn` small. The operand-bearing
640+
/// fields (`opnds`, `stack_map`) stay inline on the variant so the operand
641+
/// iteration macros can reach them by reference.
642+
#[derive(Clone)]
643+
pub struct CCallData {
644+
/// The function pointer to be called. This should be Opnd::const_ptr
645+
/// (Opnd::UImm) in most cases. gen_entry_trampoline() uses Opnd::Reg.
646+
pub fptr: Opnd,
647+
/// Optional PosMarker to remember the start address of the C call.
648+
/// It's embedded here to insert the PosMarker after push instructions
649+
/// that are split from this CCall during register assignment.
650+
pub start_marker: Option<PosMarkerFn>,
651+
/// Optional PosMarker to remember the end address of the C call.
652+
/// It's embedded here to insert the PosMarker before pop instructions
653+
/// that are split from this CCall during register assignment.
654+
pub end_marker: Option<PosMarkerFn>,
655+
pub out: Opnd,
656+
}
657+
639658
/// ZJIT Low-level IR instruction
640659
#[derive(Clone)]
641660
pub enum Insn {
@@ -683,19 +702,9 @@ pub enum Insn {
683702
// C function call with N arguments (variadic)
684703
CCall {
685704
opnds: Vec<Opnd>,
686-
/// The function pointer to be called. This should be Opnd::const_ptr
687-
/// (Opnd::UImm) in most cases. gen_entry_trampoline() uses Opnd::Reg.
688-
fptr: Opnd,
689-
/// Optional PosMarker to remember the start address of the C call.
690-
/// It's embedded here to insert the PosMarker after push instructions
691-
/// that are split from this CCall during register assignment.
692-
start_marker: Option<PosMarkerFn>,
693-
/// Optional PosMarker to remember the end address of the C call.
694-
/// It's embedded here to insert the PosMarker before pop instructions
695-
/// that are split from this CCall during register assignment.
696-
end_marker: Option<PosMarkerFn>,
697-
out: Opnd,
698705
stack_map: Option<StackMap>,
706+
/// Cold fields (fptr, markers, out), boxed to keep `Insn` small.
707+
data: Box<CCallData>,
699708
},
700709

701710
// C function return
@@ -1087,7 +1096,6 @@ impl Insn {
10871096
match self {
10881097
Insn::Add { out, .. } |
10891098
Insn::And { out, .. } |
1090-
Insn::CCall { out, .. } |
10911099
Insn::CPop { out, .. } |
10921100
Insn::CSelE { out, .. } |
10931101
Insn::CSelG { out, .. } |
@@ -1109,6 +1117,7 @@ impl Insn {
11091117
Insn::Mul { out, .. } |
11101118
Insn::URShift { out, .. } |
11111119
Insn::Xor { out, .. } => Some(out),
1120+
Insn::CCall { data, .. } => Some(&data.out),
11121121
_ => None
11131122
}
11141123
}
@@ -1119,7 +1128,6 @@ impl Insn {
11191128
match self {
11201129
Insn::Add { out, .. } |
11211130
Insn::And { out, .. } |
1122-
Insn::CCall { out, .. } |
11231131
Insn::CPop { out, .. } |
11241132
Insn::CSelE { out, .. } |
11251133
Insn::CSelG { out, .. } |
@@ -1141,6 +1149,7 @@ impl Insn {
11411149
Insn::Mul { out, .. } |
11421150
Insn::URShift { out, .. } |
11431151
Insn::Xor { out, .. } => Some(out),
1152+
Insn::CCall { data, .. } => Some(&mut data.out),
11441153
_ => None
11451154
}
11461155
}
@@ -2284,7 +2293,8 @@ impl Assembler
22842293
let mut new_ids = Vec::with_capacity(old_ids.len());
22852294

22862295
for (insn, insn_id) in old_insns.into_iter().zip(old_ids.into_iter()) {
2287-
if let Insn::CCall { opnds, out, start_marker, end_marker, fptr, stack_map } = insn {
2296+
if let Insn::CCall { opnds, stack_map, data } = insn {
2297+
let CCallData { out, start_marker, end_marker, fptr } = *data;
22882298
let insn_number = insn_id.map(|id| id.0).unwrap_or(0);
22892299
// Do we have a case where a ccall is emitted, but nobody
22902300
// uses the result?
@@ -2409,13 +2419,15 @@ impl Assembler
24092419

24102420
// The CCall itself
24112421
new_insns.push(Insn::CCall {
2412-
out: C_RET_OPND,
24132422
opnds: vec![], // We've moved everything in to ccall regs, so this should
24142423
// be empty now
2415-
start_marker: None,
2416-
end_marker: None,
2417-
fptr,
24182424
stack_map: None,
2425+
data: Box::new(CCallData {
2426+
out: C_RET_OPND,
2427+
start_marker: None,
2428+
end_marker: None,
2429+
fptr,
2430+
}),
24192431
});
24202432
new_ids.push(insn_id);
24212433

@@ -3440,7 +3452,7 @@ impl Assembler {
34403452
let out = self.new_vreg(Opnd::match_num_bits(&opnds));
34413453
let fptr = Opnd::const_ptr(fptr);
34423454
let stack_map = self.stack_map.take();
3443-
self.push_insn(Insn::CCall { fptr, opnds, start_marker: None, end_marker: None, out, stack_map });
3455+
self.push_insn(Insn::CCall { opnds, stack_map, data: Box::new(CCallData { fptr, start_marker: None, end_marker: None, out }) });
34443456
self.clear_stack_canary(canary_opnd);
34453457
out
34463458
}
@@ -3450,15 +3462,15 @@ impl Assembler {
34503462
pub fn ccall_into(&mut self, out: Opnd, fptr: *const u8, opnds: Vec<Opnd>) {
34513463
let fptr = Opnd::const_ptr(fptr);
34523464
let stack_map = self.stack_map.take();
3453-
self.push_insn(Insn::CCall { fptr, opnds, start_marker: None, end_marker: None, out, stack_map });
3465+
self.push_insn(Insn::CCall { opnds, stack_map, data: Box::new(CCallData { fptr, start_marker: None, end_marker: None, out }) });
34543466
}
34553467

34563468
/// Call a C function stored in a register
34573469
pub fn ccall_reg(&mut self, fptr: Opnd, num_bits: u8) -> Opnd {
34583470
assert!(matches!(fptr, Opnd::Reg(_)), "ccall_reg must be called with Opnd::Reg: {fptr:?}");
34593471
let out = self.new_vreg(num_bits);
34603472
let stack_map = self.stack_map.take();
3461-
self.push_insn(Insn::CCall { fptr, opnds: vec![], start_marker: None, end_marker: None, out, stack_map });
3473+
self.push_insn(Insn::CCall { opnds: vec![], stack_map, data: Box::new(CCallData { fptr, start_marker: None, end_marker: None, out }) });
34623474
out
34633475
}
34643476

@@ -3474,12 +3486,14 @@ impl Assembler {
34743486
let out = self.new_vreg(Opnd::match_num_bits(&opnds));
34753487
let stack_map = self.stack_map.take();
34763488
self.push_insn(Insn::CCall {
3477-
fptr: Opnd::const_ptr(fptr),
34783489
opnds,
3479-
start_marker: Some(Rc::new(start_marker)),
3480-
end_marker: Some(Rc::new(end_marker)),
3481-
out,
34823490
stack_map,
3491+
data: Box::new(CCallData {
3492+
fptr: Opnd::const_ptr(fptr),
3493+
start_marker: Some(Rc::new(start_marker)),
3494+
end_marker: Some(Rc::new(end_marker)),
3495+
out,
3496+
}),
34833497
});
34843498
out
34853499
}
@@ -3839,7 +3853,7 @@ mod tests {
38393853

38403854
#[test]
38413855
fn test_size_of_insn() {
3842-
assert_eq!(std::mem::size_of::<Insn>(), 144);
3856+
assert_eq!(std::mem::size_of::<Insn>(), 80);
38433857
}
38443858

38453859
#[test]
@@ -4632,11 +4646,13 @@ mod tests {
46324646
let v3 = asm.new_vreg(64);
46334647
asm.basic_blocks[b1.0].push_insn(Insn::CCall {
46344648
opnds: vec![v2],
4635-
fptr: Opnd::UImm(0xF00),
4636-
start_marker: None,
4637-
end_marker: None,
4638-
out: v3,
46394649
stack_map: None,
4650+
data: Box::new(CCallData {
4651+
fptr: Opnd::UImm(0xF00),
4652+
start_marker: None,
4653+
end_marker: None,
4654+
out: v3,
4655+
}),
46404656
});
46414657

46424658
// v4 = Add(v3, v1)

zjit/src/backend/x86_64/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,8 @@ impl Assembler {
917917
},
918918

919919
// C function call
920-
Insn::CCall { fptr, .. } => {
920+
Insn::CCall { data, .. } => {
921+
let fptr = &data.fptr;
921922
match fptr {
922923
Opnd::UImm(fptr) => {
923924
call_ptr(cb, RAX, *fptr as *const u8);

0 commit comments

Comments
 (0)