Skip to content

Commit d989bc5

Browse files
authored
YJIT: split chain_depth and flag booleans in context (#11169)
Split these values to avoid using a bit mask in the context Use variable length encoding to save a few bits on chain depth
1 parent c06f79c commit d989bc5

File tree

1 file changed

+62
-34
lines changed

1 file changed

+62
-34
lines changed

yjit/src/core.rs

Lines changed: 62 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -510,22 +510,13 @@ impl fmt::Debug for RegMapping {
510510
}
511511
}
512512

513-
/// Bits for chain_depth_return_landing_defer
514-
const RETURN_LANDING_BIT: u8 = 0b10000000;
515-
const DEFER_BIT: u8 = 0b01000000;
516-
const CHAIN_DEPTH_MASK: u8 = 0b00111111; // 63
513+
/// Maximum value of the chain depth (should fit in 5 bits)
514+
const CHAIN_DEPTH_MAX: u8 = 0b11111; // 31
517515

518516
/// Code generation context
519517
/// Contains information we can use to specialize/optimize code
520-
/// There are a lot of context objects so we try to keep the size small.
521518
#[derive(Copy, Clone, Default, Eq, Hash, PartialEq, Debug)]
522519
pub struct Context {
523-
// FIXME: decoded_from breaks == on contexts
524-
/*
525-
// Offset at which this context was previously encoded (zero if not)
526-
decoded_from: u32,
527-
*/
528-
529520
// Number of values currently on the temporary stack
530521
stack_size: u8,
531522

@@ -536,11 +527,15 @@ pub struct Context {
536527
/// Which stack temps or locals are in a register
537528
reg_mapping: RegMapping,
538529

539-
/// Fields packed into u8
540-
/// - 1st bit from the left: Whether this code is the target of a JIT-to-JIT Ruby return ([Self::is_return_landing])
541-
/// - 2nd bit from the left: Whether the compilation of this code has been deferred ([Self::is_deferred])
542-
/// - Last 6 bits (max: 63): Depth of this block in the sidechain (eg: inline-cache chain)
543-
chain_depth_and_flags: u8,
530+
// Depth of this block in the sidechain (eg: inline-cache chain)
531+
// 6 bits, max 63
532+
chain_depth: u8,
533+
534+
// Whether this code is the target of a JIT-to-JIT Ruby return ([Self::is_return_landing])
535+
is_return_landing: bool,
536+
537+
// Whether the compilation of this code has been deferred ([Self::is_deferred])
538+
is_deferred: bool,
544539

545540
// Type we track for self
546541
self_type: Type,
@@ -645,26 +640,35 @@ impl BitVector {
645640
self.push_uint(val as u64, 8);
646641
}
647642

643+
fn push_u5(&mut self, val: u8) {
644+
assert!(val <= 0b11111);
645+
self.push_uint(val as u64, 5);
646+
}
647+
648648
fn push_u4(&mut self, val: u8) {
649-
assert!(val < 16);
649+
assert!(val <= 0b1111);
650650
self.push_uint(val as u64, 4);
651651
}
652652

653653
fn push_u3(&mut self, val: u8) {
654-
assert!(val < 8);
654+
assert!(val <= 0b111);
655655
self.push_uint(val as u64, 3);
656656
}
657657

658658
fn push_u2(&mut self, val: u8) {
659-
assert!(val < 4);
659+
assert!(val <= 0b11);
660660
self.push_uint(val as u64, 2);
661661
}
662662

663663
fn push_u1(&mut self, val: u8) {
664-
assert!(val < 2);
664+
assert!(val <= 0b1);
665665
self.push_uint(val as u64, 1);
666666
}
667667

668+
fn push_bool(&mut self, val: bool) {
669+
self.push_u1(if val { 1 } else { 0 });
670+
}
671+
668672
// Push a context encoding opcode
669673
fn push_op(&mut self, op: CtxOp) {
670674
self.push_u4(op as u8);
@@ -710,6 +714,10 @@ impl BitVector {
710714
self.read_uint(bit_idx, 8) as u8
711715
}
712716

717+
fn read_u5(&self, bit_idx: &mut usize) -> u8 {
718+
self.read_uint(bit_idx, 5) as u8
719+
}
720+
713721
fn read_u4(&self, bit_idx: &mut usize) -> u8 {
714722
self.read_uint(bit_idx, 4) as u8
715723
}
@@ -726,6 +734,10 @@ impl BitVector {
726734
self.read_uint(bit_idx, 1) as u8
727735
}
728736

737+
fn read_bool(&self, bit_idx: &mut usize) -> bool {
738+
self.read_u1(bit_idx) != 0
739+
}
740+
729741
fn read_op(&self, bit_idx: &mut usize) -> CtxOp {
730742
unsafe { std::mem::transmute(self.read_u4(bit_idx)) }
731743
}
@@ -1052,8 +1064,18 @@ impl Context {
10521064
}
10531065
}
10541066

1055-
// chain_depth_and_flags: u8,
1056-
bits.push_u8(self.chain_depth_and_flags);
1067+
bits.push_bool(self.is_deferred);
1068+
bits.push_bool(self.is_return_landing);
1069+
1070+
// The chain depth is most often 0 or 1
1071+
if self.chain_depth < 2 {
1072+
bits.push_u1(0);
1073+
bits.push_u1(self.chain_depth);
1074+
1075+
} else {
1076+
bits.push_u1(1);
1077+
bits.push_u5(self.chain_depth);
1078+
}
10571079

10581080
// Encode the self type if known
10591081
if self.self_type != Type::Unknown {
@@ -1146,8 +1168,14 @@ impl Context {
11461168
}
11471169
}
11481170

1149-
// chain_depth_and_flags: u8
1150-
ctx.chain_depth_and_flags = bits.read_u8(&mut idx);
1171+
ctx.is_deferred = bits.read_bool(&mut idx);
1172+
ctx.is_return_landing = bits.read_bool(&mut idx);
1173+
1174+
if bits.read_u1(&mut idx) == 0 {
1175+
ctx.chain_depth = bits.read_u1(&mut idx)
1176+
} else {
1177+
ctx.chain_depth = bits.read_u5(&mut idx)
1178+
}
11511179

11521180
loop {
11531181
//println!("reading op");
@@ -2483,39 +2511,39 @@ impl Context {
24832511
}
24842512

24852513
pub fn get_chain_depth(&self) -> u8 {
2486-
self.chain_depth_and_flags & CHAIN_DEPTH_MASK
2514+
self.chain_depth
24872515
}
24882516

24892517
pub fn reset_chain_depth_and_defer(&mut self) {
2490-
self.chain_depth_and_flags &= !CHAIN_DEPTH_MASK;
2491-
self.chain_depth_and_flags &= !DEFER_BIT;
2518+
self.chain_depth = 0;
2519+
self.is_deferred = false;
24922520
}
24932521

24942522
pub fn increment_chain_depth(&mut self) {
2495-
if self.get_chain_depth() == CHAIN_DEPTH_MASK {
2523+
if self.get_chain_depth() == CHAIN_DEPTH_MAX {
24962524
panic!("max block version chain depth reached!");
24972525
}
2498-
self.chain_depth_and_flags += 1;
2526+
self.chain_depth += 1;
24992527
}
25002528

25012529
pub fn set_as_return_landing(&mut self) {
2502-
self.chain_depth_and_flags |= RETURN_LANDING_BIT;
2530+
self.is_return_landing = true;
25032531
}
25042532

25052533
pub fn clear_return_landing(&mut self) {
2506-
self.chain_depth_and_flags &= !RETURN_LANDING_BIT;
2534+
self.is_return_landing = false;
25072535
}
25082536

25092537
pub fn is_return_landing(&self) -> bool {
2510-
self.chain_depth_and_flags & RETURN_LANDING_BIT != 0
2538+
self.is_return_landing
25112539
}
25122540

25132541
pub fn mark_as_deferred(&mut self) {
2514-
self.chain_depth_and_flags |= DEFER_BIT;
2542+
self.is_deferred = true;
25152543
}
25162544

25172545
pub fn is_deferred(&self) -> bool {
2518-
self.chain_depth_and_flags & DEFER_BIT != 0
2546+
self.is_deferred
25192547
}
25202548

25212549
/// Get an operand for the adjusted stack pointer address

0 commit comments

Comments
 (0)