1use std::collections::HashSet;
2use std::mem::swap;
3use std::sync::Mutex;
4
5use crate::util::ObjectReference;
6
7use super::object_enum::ObjectEnumerator;
8
9pub struct TreadMill {
13 sync: Mutex<TreadMillSync>,
14}
15
16#[derive(Default)]
18struct TreadMillSync {
19 from_space: HashSet<ObjectReference>,
21 to_space: HashSet<ObjectReference>,
24 collect_nursery: HashSet<ObjectReference>,
26 alloc_nursery: HashSet<ObjectReference>,
29}
30
31impl std::fmt::Debug for TreadMill {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 let sync = self.sync.lock().unwrap();
34 f.debug_struct("TreadMill")
35 .field("from_space", &sync.from_space)
36 .field("to_space", &sync.to_space)
37 .field("collect_nursery", &sync.collect_nursery)
38 .field("alloc_nursery", &sync.alloc_nursery)
39 .finish()
40 }
41}
42
43impl TreadMill {
44 pub fn new() -> Self {
45 TreadMill {
46 sync: Mutex::new(Default::default()),
47 }
48 }
49
50 pub fn add_to_treadmill(&self, object: ObjectReference, nursery: bool) {
55 let mut sync = self.sync.lock().unwrap();
56 if nursery {
57 trace!("Adding {} to alloc_nursery", object);
58 sync.alloc_nursery.insert(object);
59 } else {
60 trace!("Adding {} to to_space", object);
61 sync.to_space.insert(object);
62 }
63 }
64
65 pub fn collect_nursery(&self) -> impl IntoIterator<Item = ObjectReference> {
68 let mut sync = self.sync.lock().unwrap();
69 std::mem::take(&mut sync.collect_nursery)
70 }
71
72 pub fn collect_alloc_nursery(&self) -> impl IntoIterator<Item = ObjectReference> {
74 let mut sync = self.sync.lock().unwrap();
75 std::mem::take(&mut sync.alloc_nursery)
76 }
77
78 pub fn collect_mature(&self) -> impl IntoIterator<Item = ObjectReference> {
81 let mut sync = self.sync.lock().unwrap();
82 std::mem::take(&mut sync.from_space)
83 }
84
85 pub fn retain_mature(&self, f: impl FnMut(&ObjectReference) -> bool) {
87 let mut sync = self.sync.lock().unwrap();
88 sync.to_space.retain(f);
89 }
90
91 pub fn remove_mature(&self, object: ObjectReference) -> bool {
94 let mut sync = self.sync.lock().unwrap();
95 assert!(sync.from_space.is_empty());
96 sync.to_space.remove(&object)
97 }
98
99 pub fn copy(&self, object: ObjectReference, is_in_nursery: bool) {
101 let mut sync = self.sync.lock().unwrap();
102 if is_in_nursery {
103 debug_assert!(
104 sync.collect_nursery.contains(&object),
105 "copy source object ({}) must be in collect_nursery",
106 object
107 );
108 sync.collect_nursery.remove(&object);
109 } else {
110 debug_assert!(
111 sync.from_space.contains(&object),
112 "copy source object ({}) must be in from_space",
113 object
114 );
115 sync.from_space.remove(&object);
116 }
117 sync.to_space.insert(object);
118 }
119
120 pub fn is_to_space_empty(&self) -> bool {
122 let sync = self.sync.lock().unwrap();
123 sync.to_space.is_empty()
124 }
125
126 pub fn is_from_space_empty(&self) -> bool {
128 let sync = self.sync.lock().unwrap();
129 sync.from_space.is_empty()
130 }
131
132 pub fn is_alloc_nursery_empty(&self) -> bool {
134 let sync = self.sync.lock().unwrap();
135 sync.alloc_nursery.is_empty()
136 }
137
138 pub fn is_collect_nursery_empty(&self) -> bool {
140 let sync = self.sync.lock().unwrap();
141 sync.collect_nursery.is_empty()
142 }
143
144 pub fn flip(&mut self, full_heap: bool) {
150 let sync = self.sync.get_mut().unwrap();
151 swap(&mut sync.alloc_nursery, &mut sync.collect_nursery);
152 trace!("Flipped alloc_nursery and collect_nursery");
153 if full_heap {
154 swap(&mut sync.from_space, &mut sync.to_space);
155 trace!("Flipped from_space and to_space");
156 }
157 }
158
159 pub(crate) fn enumerate_objects(&self, enumerator: &mut dyn ObjectEnumerator, all: bool) {
166 let sync = self.sync.lock().unwrap();
167 let mut enumerated = 0usize;
168 let mut visit_objects = |set: &HashSet<ObjectReference>| {
169 for object in set.iter() {
170 enumerator.visit_object(*object);
171 enumerated += 1;
172 }
173 };
174 visit_objects(&sync.alloc_nursery);
175 visit_objects(&sync.to_space);
176
177 if all {
178 visit_objects(&sync.collect_nursery);
179 visit_objects(&sync.from_space);
180 }
181
182 debug!("Enumerated {enumerated} objects in LOS. all: {all}. from_space: {fs}, to_space: {ts}, collect_nursery: {cn}, alloc_nursery: {an}",
183 fs=sync.from_space.len(),
184 ts=sync.to_space.len(),
185 cn=sync.collect_nursery.len(),
186 an=sync.alloc_nursery.len(),
187 );
188 }
189}
190
191impl Default for TreadMill {
192 fn default() -> Self {
193 Self::new()
194 }
195}