@@ -2,12 +2,12 @@ use std::sync::Mutex;
22
33use mmtk:: {
44 scheduler:: { GCWork , GCWorker , WorkBucketStage } ,
5- util:: ObjectReference ,
5+ util:: { Address , ObjectReference } ,
66 vm:: ObjectTracerContext ,
77} ;
88
99use crate :: {
10- abi:: { self , GCThreadTLS } ,
10+ abi:: { self , GCThreadTLS , Qundef , VALUE } ,
1111 extra_assert, is_mmtk_object_safe, upcalls, Ruby ,
1212} ;
1313
@@ -27,11 +27,15 @@ pub enum WeakConcurrentSetKind {
2727 GlobalSymbols = abi:: MMTK_WEAK_CONCURRENT_SET_KIND_GLOBAL_SYMBOLS ,
2828}
2929
30+ pub type FieldType = * mut VALUE ;
31+
3032pub struct WeakProcessor {
3133 /// Objects that needs `obj_free` called when dying.
3234 /// If it is a bottleneck, replace it with a lock-free data structure,
3335 /// or add candidates in batch.
3436 obj_free_candidates : Mutex < Vec < ObjectReference > > ,
37+ /// Weak fields discovered during the current GC.
38+ weak_fields : Mutex < Vec < FieldType > > ,
3539}
3640
3741impl Default for WeakProcessor {
@@ -44,6 +48,7 @@ impl WeakProcessor {
4448 pub fn new ( ) -> Self {
4549 Self {
4650 obj_free_candidates : Mutex :: new ( Vec :: new ( ) ) ,
51+ weak_fields : Default :: default ( ) ,
4752 }
4853 }
4954
@@ -70,6 +75,28 @@ impl WeakProcessor {
7075 std:: mem:: take ( obj_free_candidates. as_mut ( ) )
7176 }
7277
78+ pub fn clear_weak_fields ( & self ) {
79+ let mut weak_fields = self
80+ . weak_fields
81+ . try_lock ( )
82+ . expect ( "Should not have contention." ) ;
83+ weak_fields. clear ( ) ;
84+ }
85+
86+ pub fn discover_weak_field ( & self , field : FieldType ) {
87+ let mut weak_fields = self . weak_fields . lock ( ) . unwrap ( ) ;
88+ weak_fields. push ( field) ;
89+ trace ! ( "Pushed weak field {field:?}" ) ;
90+ }
91+
92+ pub fn get_all_weak_fields ( & self ) -> Vec < FieldType > {
93+ let mut weak_fields = self
94+ . weak_fields
95+ . try_lock ( )
96+ . expect ( "Should not have contention." ) ;
97+ std:: mem:: take ( & mut weak_fields)
98+ }
99+
73100 pub fn process_weak_stuff (
74101 & self ,
75102 worker : & mut GCWorker < Ruby > ,
@@ -88,6 +115,7 @@ impl WeakProcessor {
88115 Box :: new( UpdateCCRefinementTable ) as _,
89116 // END: Weak tables
90117 Box :: new( UpdateWbUnprotectedObjectsList ) as _,
118+ Box :: new( UpdateWeakFields ) as _,
91119 ] ) ;
92120
93121 if SPECIALIZE_FSTRING_TABLE_PROCESSING {
@@ -317,3 +345,49 @@ impl Forwardable for ObjectReference {
317345 self . get_forwarded_object ( ) . unwrap_or ( * self )
318346 }
319347}
348+
349+ struct UpdateWeakFields ;
350+
351+ impl GCWork < Ruby > for UpdateWeakFields {
352+ fn do_work ( & mut self , _worker : & mut GCWorker < Ruby > , _mmtk : & ' static mmtk:: MMTK < Ruby > ) {
353+ let weak_fields = crate :: binding ( ) . weak_proc . get_all_weak_fields ( ) ;
354+
355+ let num_fields = weak_fields. len ( ) ;
356+ let mut live = 0usize ;
357+ let mut forwarded = 0usize ;
358+
359+ debug ! ( "Updating {num_fields} weak fields..." ) ;
360+
361+ for field in weak_fields {
362+ let old_value = unsafe { * field } ;
363+ trace ! ( " Visiting weak field {field:?} -> {old_value:?}" ) ;
364+
365+ if old_value. is_special_const ( ) {
366+ continue ;
367+ }
368+
369+ let addr = unsafe { Address :: from_usize ( old_value. 0 ) } ;
370+ if !addr. is_mapped ( ) {
371+ panic ! ( "Field {field:?} value {addr} points to unmapped area" ) ;
372+ }
373+ let Some ( old_objref) = mmtk:: memory_manager:: is_mmtk_object ( addr) else {
374+ panic ! ( "Field {field:?} value {addr} is an invalid object reference" ) ;
375+ } ;
376+
377+ if old_objref. is_reachable ( ) {
378+ live += 1 ;
379+ if let Some ( new_objref) = old_objref. get_forwarded_object ( ) {
380+ forwarded += 1 ;
381+ let new_value = VALUE :: from ( new_objref) ;
382+ trace ! ( " Updated weak field {field:?} to {new_value:?}" ) ;
383+ unsafe { * field = new_value } ;
384+ }
385+ } else {
386+ unsafe { * field = Qundef } ;
387+ }
388+ }
389+
390+ debug ! ( "Updated {num_fields} weak fields. {live} live, {forwarded} forwarded." ) ;
391+ probe ! ( mmtk_ruby, update_weak_fields, num_fields, live, forwarded) ;
392+ }
393+ }
0 commit comments