@@ -636,6 +636,25 @@ impl From<CodePtr> for Target {
636636
637637type 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 ) ]
641660pub 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)
0 commit comments