@@ -16,8 +16,10 @@ pub fn scan_finalizers_in_rust<T: ObjectTracer>(tracer: &mut T) {
16
16
let jl_gc_have_pending_finalizers: * mut i32 =
17
17
unsafe { ( ( * UPCALLS ) . get_jl_gc_have_pending_finalizers ) ( ) } ;
18
18
19
+ // Current length of marked list: we only need to trace objects after this length if this is a nursery GC.
19
20
let mut orig_marked_len = marked_finalizers_list. len ;
20
21
22
+ // Sweep thread local list: if they are not alive, move to to_finalize.
21
23
for mutator in <JuliaVM as VMBinding >:: VMActivePlan :: mutators ( ) {
22
24
let list = ArrayListT :: thread_local_finalizer_list ( mutator) ;
23
25
sweep_finalizer_list (
@@ -28,7 +30,8 @@ pub fn scan_finalizers_in_rust<T: ObjectTracer>(tracer: &mut T) {
28
30
) ;
29
31
}
30
32
31
- if !crate :: api:: mmtk_is_current_gc_nursery ( ) {
33
+ // If this is a full heap GC, we also sweep marked list.
34
+ if !crate :: collection:: is_current_gc_nursery ( ) {
32
35
sweep_finalizer_list (
33
36
marked_finalizers_list,
34
37
to_finalize,
@@ -38,12 +41,14 @@ pub fn scan_finalizers_in_rust<T: ObjectTracer>(tracer: &mut T) {
38
41
orig_marked_len = 0 ;
39
42
}
40
43
44
+ // Go through thread local list again and trace objects
41
45
for mutator in <JuliaVM as VMBinding >:: VMActivePlan :: mutators ( ) {
42
46
let list = ArrayListT :: thread_local_finalizer_list ( mutator) ;
43
47
mark_finlist ( list, 0 , tracer) ;
44
48
}
45
-
49
+ // Trace new objects in marked list
46
50
mark_finlist ( marked_finalizers_list, orig_marked_len, tracer) ;
51
+ // Trace objects in to_finalize (which are just pushed in sweeping thread local list)
47
52
mark_finlist ( to_finalize, 0 , tracer) ;
48
53
}
49
54
@@ -105,11 +110,20 @@ impl ArrayListT {
105
110
}
106
111
}
107
112
113
+ fn gc_ptr_clear_tag ( addr : Address , tag : usize ) -> ObjectReference {
114
+ ObjectReference :: from_raw_address ( unsafe { Address :: from_usize ( addr & !tag) } )
115
+ }
116
+
117
+ fn gc_ptr_tag ( addr : Address , tag : usize ) -> bool {
118
+ addr & tag != 0
119
+ }
120
+
108
121
// sweep_finalizer_list in gc.c
109
- // finalizer_list_marked is None if list is finalizer_list_marked.
110
122
fn sweep_finalizer_list (
111
123
list : & mut ArrayListT ,
112
124
to_finalize : & mut ArrayListT ,
125
+ // finalizer_list_marked is None if list (1st parameter) is finalizer_list_marked.
126
+ // Rust does not allow sending the same mutable reference as two different arguments (cannot borrow __ as mutable more than once at a time)
113
127
mut finalizer_list_marked : Option < & mut ArrayListT > ,
114
128
jl_gc_have_pending_finalizers : * mut i32 ,
115
129
) {
@@ -121,19 +135,20 @@ fn sweep_finalizer_list(
121
135
let mut j = 0 ;
122
136
while i < list. len {
123
137
let v0: Address = list. get ( i) ;
124
- let v = unsafe { ObjectReference :: from_raw_address ( Address :: from_usize ( v0 & ( ! 3usize ) ) ) } ;
138
+ let v = gc_ptr_clear_tag ( v0 , 3 ) ;
125
139
if v0. is_zero ( ) {
126
140
i += 2 ;
127
141
// remove from this list
128
142
continue ;
129
143
}
130
144
131
145
let fin = list. get ( i + 1 ) ;
132
- let ( isfreed, isold) = if v0 & 2usize != 0 {
146
+ let ( isfreed, isold) = if gc_ptr_tag ( v0 , 2 ) {
133
147
( true , false )
134
148
} else {
135
149
let isfreed = !memory_manager:: is_live_object ( v) ;
136
- ( isfreed, finalizer_list_marked. is_some ( ) && !isfreed)
150
+ let isold = finalizer_list_marked. is_some ( ) && !isfreed;
151
+ ( isfreed, isold)
137
152
} ;
138
153
if isfreed || isold {
139
154
// remove from this list
@@ -176,22 +191,22 @@ fn mark_finlist<T: ObjectTracer>(list: &mut ArrayListT, start: usize, tracer: &m
176
191
continue ;
177
192
}
178
193
179
- let obj = if cur & 1usize != 0 {
194
+ let new_obj = if gc_ptr_tag ( cur, 1 ) {
180
195
// Skip next
181
196
i += 1 ;
182
197
debug_assert ! ( i < list. len) ;
183
- ObjectReference :: from_raw_address ( unsafe { Address :: from_usize ( cur & ( ! 1usize ) ) } )
198
+ gc_ptr_clear_tag ( cur, 1 )
184
199
} else {
185
200
ObjectReference :: from_raw_address ( cur)
186
201
} ;
187
- if cur & 2usize != 0 {
202
+ if gc_ptr_tag ( cur, 2 ) {
188
203
i += 1 ;
189
204
continue ;
190
205
}
191
206
192
- let traced = tracer. trace_object ( obj ) ;
207
+ let traced = tracer. trace_object ( new_obj ) ;
193
208
debug_assert_eq ! (
194
- traced, obj ,
209
+ traced, new_obj ,
195
210
"Object is moved -- we need to save the new object back to the finalizer list"
196
211
) ;
197
212
i += 1 ;
0 commit comments