1use crate::internal::gc_info::GCInfoIndex;
2use modular_bitfield::prelude::*;
3use std::mem::size_of;
4
5#[derive(Clone, Copy)]
30#[repr(C)]
31pub struct HeapObjectHeader {
32 #[cfg(target_pointer_width = "64")]
33 _padding: u32,
34 encoded_high: EncodedHigh,
35 encoded_low: u16,
36}
37
38pub const ALLOCATION_GRANULARITY: usize = size_of::<usize>();
39
40impl HeapObjectHeader {
41 pub fn is_precise(&self) -> bool {
43 self.get_size() == 0
44 }
45 pub fn set_free(&mut self) {
47 self.encoded_low = 0;
48 }
49 #[inline(always)]
51 pub unsafe fn from_object(obj: *const u8) -> *mut Self {
52 (obj as usize - size_of::<Self>()) as _
53 }
54 #[inline(always)]
56 pub fn payload(&self) -> *const u8 {
57 (self as *const Self as usize + size_of::<Self>()) as _
58 }
59 #[inline(always)]
61 pub fn get_gc_info_index(&self) -> GCInfoIndex {
62 debug_assert!(
63 self.encoded_low > 0,
64 "Trying to access non-allocated header {:p} (idx {})",
65 self,
66 self.encoded_low
67 );
68 GCInfoIndex(self.encoded_low)
69 }
70 #[inline(always)]
72 pub fn get_size(self) -> usize {
73 let size = self.encoded_high.size();
74 size as usize * ALLOCATION_GRANULARITY
75 }
76 #[inline(always)]
77 pub fn set_size(&mut self, size: usize) {
78 self.encoded_high
79 .set_size((size / ALLOCATION_GRANULARITY) as _);
80 }
81 #[inline(always)]
82 pub fn is_grey(self) -> bool {
83 self.encoded_high.state() == CellState::PossiblyGrey
84 }
85 #[inline(always)]
86 pub fn is_white(self) -> bool {
87 self.encoded_high.state() == CellState::DefinitelyWhite
88 }
89 #[inline(always)]
90 pub fn is_black(self) -> bool {
91 self.encoded_high.state() == CellState::PossiblyBlack
92 }
93
94 #[inline(always)]
95 pub fn set_state(&mut self, current: CellState, new: CellState) -> bool {
96 if self.encoded_high.state() != current {
97 return false;
98 }
99 self.encoded_high.set_state(new);
100 debug_assert_eq!(self.state(), new);
101 true
102 }
103 #[inline(always)]
104 pub fn force_set_state(&mut self, state: CellState) {
105 self.encoded_high.set_state(state);
106 }
107 #[inline(always)]
108 pub fn set_gc_info(&mut self, index: GCInfoIndex) {
109 self.encoded_low = index.0;
110 }
111 #[inline(always)]
112 pub fn is_free(&self) -> bool {
113 self.get_gc_info_index().0 == 0
114 }
115
116 #[inline]
117 pub fn state(&self) -> CellState {
118 self.encoded_high.state()
119 }
120}
121
122#[bitfield(bits = 16)]
123#[derive(Clone, Copy)]
124pub struct EncodedHigh {
125 size: B13,
126 #[allow(dead_code)]
127 pinned: B1,
128 #[bits = 2]
129 state: CellState,
130}
131
132#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord, BitfieldSpecifier)]
133#[bits = 2]
134pub enum CellState {
135 DefinitelyWhite,
136 PossiblyGrey,
137 PossiblyBlack,
138}