Skip to content

Commit 167058d

Browse files
authored
Replace TransitiveClosure with EdgeVisitor (#148)
* Replace TransitiveClosure with EdgeVisitor In respond to an upstream API change, we now use EdgeVisitor for object scanning. This also removes `unreachable!()` implementations for `process_node()`. * Remove ObjectsClosure ObjectsClosure was moved to mmtk-core. Now `scan_objects` is implemented in mmtk-core.
1 parent 86c6f53 commit 167058d

File tree

3 files changed

+25
-93
lines changed

3 files changed

+25
-93
lines changed

mmtk/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ once_cell = "1.10.0"
2828
# - change branch
2929
# - change repo name
3030
# But other changes including adding/removing whitespaces in commented lines may break the CI.
31-
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "be96a270815c0f20a169a7214eebccfe50484be4" }
31+
mmtk = { git = "https://github.com/mmtk/mmtk-core.git", rev = "0babba20290d3c4e4cdb2a83284aa7204c9a23cc" }
3232
# Uncomment the following to build locally
3333
# mmtk = { path = "../repos/mmtk-core" }
3434

mmtk/src/object_scanning.rs

Lines changed: 17 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,29 @@
11
use super::abi::*;
22
use super::UPCALLS;
3-
use crate::{OpenJDK, SINGLETON};
4-
use mmtk::scheduler::ProcessEdgesWork;
5-
use mmtk::scheduler::{GCWorker, WorkBucketStage};
63
use mmtk::util::constants::*;
74
use mmtk::util::opaque_pointer::*;
85
use mmtk::util::{Address, ObjectReference};
9-
use mmtk::TransitiveClosure;
10-
use std::marker::PhantomData;
6+
use mmtk::vm::EdgeVisitor;
117
use std::{mem, slice};
128

139
trait OopIterate: Sized {
14-
fn oop_iterate(&self, oop: Oop, closure: &mut impl TransitiveClosure);
10+
fn oop_iterate(&self, oop: Oop, closure: &mut impl EdgeVisitor);
1511
}
1612

1713
impl OopIterate for OopMapBlock {
1814
#[inline]
19-
fn oop_iterate(&self, oop: Oop, closure: &mut impl TransitiveClosure) {
15+
fn oop_iterate(&self, oop: Oop, closure: &mut impl EdgeVisitor) {
2016
let start = oop.get_field_address(self.offset);
2117
for i in 0..self.count as usize {
2218
let edge = start + (i << LOG_BYTES_IN_ADDRESS);
23-
closure.process_edge(edge);
19+
closure.visit_edge(edge);
2420
}
2521
}
2622
}
2723

2824
impl OopIterate for InstanceKlass {
2925
#[inline]
30-
fn oop_iterate(&self, oop: Oop, closure: &mut impl TransitiveClosure) {
26+
fn oop_iterate(&self, oop: Oop, closure: &mut impl EdgeVisitor) {
3127
let oop_maps = self.nonstatic_oop_maps();
3228
for map in oop_maps {
3329
map.oop_iterate(oop, closure)
@@ -37,7 +33,7 @@ impl OopIterate for InstanceKlass {
3733

3834
impl OopIterate for InstanceMirrorKlass {
3935
#[inline]
40-
fn oop_iterate(&self, oop: Oop, closure: &mut impl TransitiveClosure) {
36+
fn oop_iterate(&self, oop: Oop, closure: &mut impl EdgeVisitor) {
4137
self.instance_klass.oop_iterate(oop, closure);
4238
// if (Devirtualizer::do_metadata(closure)) {
4339
// Klass* klass = java_lang_Class::as_Klass(obj);
@@ -71,14 +67,14 @@ impl OopIterate for InstanceMirrorKlass {
7167
let len = Self::static_oop_field_count(oop);
7268
let slice = unsafe { slice::from_raw_parts(start, len as _) };
7369
for oop in slice {
74-
closure.process_edge(Address::from_ref(oop as &Oop));
70+
closure.visit_edge(Address::from_ref(oop as &Oop));
7571
}
7672
}
7773
}
7874

7975
impl OopIterate for InstanceClassLoaderKlass {
8076
#[inline]
81-
fn oop_iterate(&self, oop: Oop, closure: &mut impl TransitiveClosure) {
77+
fn oop_iterate(&self, oop: Oop, closure: &mut impl EdgeVisitor) {
8278
self.instance_klass.oop_iterate(oop, closure);
8379
// if (Devirtualizer::do_metadata(closure)) {
8480
// ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj);
@@ -92,42 +88,42 @@ impl OopIterate for InstanceClassLoaderKlass {
9288

9389
impl OopIterate for ObjArrayKlass {
9490
#[inline]
95-
fn oop_iterate(&self, oop: Oop, closure: &mut impl TransitiveClosure) {
91+
fn oop_iterate(&self, oop: Oop, closure: &mut impl EdgeVisitor) {
9692
let array = unsafe { oop.as_array_oop() };
9793
for oop in unsafe { array.data::<Oop>(BasicType::T_OBJECT) } {
98-
closure.process_edge(Address::from_ref(oop as &Oop));
94+
closure.visit_edge(Address::from_ref(oop as &Oop));
9995
}
10096
}
10197
}
10298

10399
impl OopIterate for TypeArrayKlass {
104100
#[inline]
105-
fn oop_iterate(&self, _oop: Oop, _closure: &mut impl TransitiveClosure) {
101+
fn oop_iterate(&self, _oop: Oop, _closure: &mut impl EdgeVisitor) {
106102
// Performance tweak: We skip processing the klass pointer since all
107103
// TypeArrayKlasses are guaranteed processed via the null class loader.
108104
}
109105
}
110106

111107
impl OopIterate for InstanceRefKlass {
112108
#[inline]
113-
fn oop_iterate(&self, oop: Oop, closure: &mut impl TransitiveClosure) {
109+
fn oop_iterate(&self, oop: Oop, closure: &mut impl EdgeVisitor) {
114110
self.instance_klass.oop_iterate(oop, closure);
115111
let referent_addr = Self::referent_address(oop);
116-
closure.process_edge(referent_addr);
112+
closure.visit_edge(referent_addr);
117113
let discovered_addr = Self::discovered_address(oop);
118-
closure.process_edge(discovered_addr);
114+
closure.visit_edge(discovered_addr);
119115
}
120116
}
121117

122118
#[allow(unused)]
123-
fn oop_iterate_slow(oop: Oop, closure: &mut impl TransitiveClosure, tls: OpaquePointer) {
119+
fn oop_iterate_slow(oop: Oop, closure: &mut impl EdgeVisitor, tls: OpaquePointer) {
124120
unsafe {
125121
((*UPCALLS).scan_object)(closure as *mut _ as _, mem::transmute(oop), tls);
126122
}
127123
}
128124

129125
#[inline]
130-
fn oop_iterate(oop: Oop, closure: &mut impl TransitiveClosure) {
126+
fn oop_iterate(oop: Oop, closure: &mut impl EdgeVisitor) {
131127
let klass_id = oop.klass.id;
132128
debug_assert!(
133129
klass_id as i32 >= 0 && (klass_id as i32) < 6,
@@ -164,68 +160,11 @@ fn oop_iterate(oop: Oop, closure: &mut impl TransitiveClosure) {
164160
}
165161

166162
#[inline]
167-
pub fn scan_object(
168-
object: ObjectReference,
169-
closure: &mut impl TransitiveClosure,
170-
_tls: VMWorkerThread,
171-
) {
163+
pub fn scan_object(object: ObjectReference, closure: &mut impl EdgeVisitor, _tls: VMWorkerThread) {
172164
// println!("*****scan_object(0x{:x}) -> \n 0x{:x}, 0x{:x} \n",
173165
// object,
174166
// unsafe { *(object.value() as *const usize) },
175167
// unsafe { *((object.value() + 8) as *const usize) }
176168
// );
177169
unsafe { oop_iterate(mem::transmute(object), closure) }
178170
}
179-
180-
pub struct ObjectsClosure<'a, E: ProcessEdgesWork<VM = OpenJDK>>(
181-
Vec<Address>,
182-
&'a mut GCWorker<OpenJDK>,
183-
PhantomData<E>,
184-
);
185-
186-
impl<'a, E: ProcessEdgesWork<VM = OpenJDK>> TransitiveClosure for ObjectsClosure<'a, E> {
187-
#[inline]
188-
fn process_edge(&mut self, slot: Address) {
189-
if self.0.is_empty() {
190-
self.0.reserve(E::CAPACITY);
191-
}
192-
self.0.push(slot);
193-
if self.0.len() >= E::CAPACITY {
194-
let mut new_edges = Vec::new();
195-
mem::swap(&mut new_edges, &mut self.0);
196-
self.1.add_work(
197-
WorkBucketStage::Closure,
198-
E::new(new_edges, false, &SINGLETON),
199-
);
200-
}
201-
}
202-
fn process_node(&mut self, _object: ObjectReference) {
203-
unreachable!()
204-
}
205-
}
206-
207-
impl<'a, E: ProcessEdgesWork<VM = OpenJDK>> Drop for ObjectsClosure<'a, E> {
208-
#[inline]
209-
fn drop(&mut self) {
210-
let mut new_edges = Vec::new();
211-
mem::swap(&mut new_edges, &mut self.0);
212-
self.1.add_work(
213-
WorkBucketStage::Closure,
214-
E::new(new_edges, false, &SINGLETON),
215-
);
216-
}
217-
}
218-
219-
pub fn scan_objects_and_create_edges_work<E: ProcessEdgesWork<VM = OpenJDK>>(
220-
objects: &[ObjectReference],
221-
worker: &mut GCWorker<OpenJDK>,
222-
) {
223-
let mut closure = ObjectsClosure::<E>(Vec::new(), worker, PhantomData);
224-
for object in objects {
225-
scan_object(
226-
*object,
227-
&mut closure,
228-
VMWorkerThread(VMThread::UNINITIALIZED),
229-
);
230-
}
231-
}

mmtk/src/scanning.rs

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ use super::{NewBuffer, SINGLETON, UPCALLS};
33
use crate::OpenJDK;
44
use mmtk::memory_manager;
55
use mmtk::scheduler::ProcessEdgesWork;
6-
use mmtk::scheduler::{GCWorker, WorkBucketStage};
6+
use mmtk::scheduler::WorkBucketStage;
77
use mmtk::util::opaque_pointer::*;
88
use mmtk::util::{Address, ObjectReference};
9-
use mmtk::vm::Scanning;
9+
use mmtk::vm::{EdgeVisitor, Scanning};
10+
use mmtk::Mutator;
1011
use mmtk::MutatorContext;
11-
use mmtk::{Mutator, TransitiveClosure};
1212

1313
pub struct VMScanning {}
1414

@@ -39,26 +39,19 @@ impl Scanning<OpenJDK> for VMScanning {
3939
const SCAN_MUTATORS_IN_SAFEPOINT: bool = false;
4040
const SINGLE_THREAD_MUTATOR_SCANNING: bool = false;
4141

42-
fn scan_object<T: TransitiveClosure>(
43-
trace: &mut T,
44-
object: ObjectReference,
42+
fn scan_object<EV: EdgeVisitor>(
4543
tls: VMWorkerThread,
44+
object: ObjectReference,
45+
edge_visitor: &mut EV,
4646
) {
47-
crate::object_scanning::scan_object(object, trace, tls)
47+
crate::object_scanning::scan_object(object, edge_visitor, tls)
4848
}
4949

5050
fn notify_initial_thread_scan_complete(_partial_scan: bool, _tls: VMWorkerThread) {
5151
// unimplemented!()
5252
// TODO
5353
}
5454

55-
fn scan_objects<W: ProcessEdgesWork<VM = OpenJDK>>(
56-
objects: &[ObjectReference],
57-
worker: &mut GCWorker<OpenJDK>,
58-
) {
59-
crate::object_scanning::scan_objects_and_create_edges_work::<W>(objects, worker);
60-
}
61-
6255
fn scan_thread_roots<W: ProcessEdgesWork<VM = OpenJDK>>() {
6356
let process_edges = create_process_edges_work::<W>;
6457
unsafe {

0 commit comments

Comments
 (0)