@@ -69,6 +69,13 @@ static GHashTable* late_handles;
6969typedef struct ephemeron_node ephemeron_node ;
7070static ephemeron_node * ephemeron_list ;
7171
72+ static OnThreadsSuspendedCallback s_on_threads_suspended ;
73+ static void * s_on_threads_suspended_arg ;
74+ static OnHandleFoundCallback s_on_handle_found ;
75+ static void * s_on_handle_found_arg ;
76+ static OnProcessCallback s_on_process ;
77+ static void * s_on_process_arg ;
78+
7279static void
7380mono_push_other_roots (void );
7481
@@ -583,6 +590,8 @@ on_gc_notification (GC_EventType event)
583590 case GC_EVENT_POST_STOP_WORLD :
584591 e = MONO_GC_EVENT_POST_STOP_WORLD ;
585592 MONO_GC_WORLD_STOP_END ();
593+ if (s_on_threads_suspended )
594+ s_on_threads_suspended (s_on_threads_suspended_arg );
586595 break ;
587596
588597 case GC_EVENT_PRE_START_WORLD :
@@ -2194,10 +2203,52 @@ mono_clear_ephemerons (void)
21942203 }
21952204}
21962205
2206+ //LateHandleCallback s_late_handle_callback;
2207+ //void* s_late_handle_callback_user_data;
2208+
2209+
2210+
2211+ void
2212+ mono_gc_collect_assets (
2213+ OnThreadsSuspendedCallback on_threads_suspended , void * on_threads_suspended_arg ,
2214+ OnHandleFoundCallback on_handle_found , void * on_handle_found_arg ,
2215+ OnProcessCallback on_process , void * on_process_arg )
2216+ {
2217+ s_on_threads_suspended = on_threads_suspended ;
2218+ s_on_threads_suspended_arg = on_threads_suspended_arg ;
2219+ s_on_handle_found = on_handle_found ;
2220+ s_on_handle_found_arg = on_handle_found_arg ;
2221+ s_on_process = on_process ;
2222+ s_on_process_arg = on_process_arg ;
2223+ mono_gc_collect (mono_gc_max_generation ());
2224+ s_on_threads_suspended = NULL ;
2225+ s_on_threads_suspended_arg = NULL ;
2226+ s_on_handle_found = NULL ;
2227+ s_on_handle_found_arg = NULL ;
2228+ s_on_process = NULL ;
2229+ s_on_process_arg = NULL ;
2230+ }
2231+
2232+ typedef struct {
2233+ struct GC_ms_entry * mark_stack_ptr ;
2234+ struct GC_ms_entry * mark_stack_limit ;
2235+ } MarkHandleData ;
2236+
2237+ MarkHandleData * s_mark_data ;
2238+
2239+
2240+ void mono_gchandle_mark_object (MonoObject * obj )
2241+ {
2242+ g_assert (s_mark_data );
2243+ s_mark_data -> mark_stack_ptr = GC_mark_and_push (obj , s_mark_data -> mark_stack_ptr , s_mark_data -> mark_stack_limit , NULL );
2244+ }
2245+
21972246static struct GC_ms_entry *
21982247mono_push_ephemerons (struct GC_ms_entry * mark_stack_ptr , struct GC_ms_entry * mark_stack_limit )
21992248{
2249+ struct GC_ms_entry * mark_stack_ptr_orig = mark_stack_ptr ;
22002250 /* push late GC handles */
2251+ if (s_on_handle_found )
22012252 {
22022253 GHashTableIter iter ;
22032254 g_hash_table_iter_init (& iter , late_handles );
@@ -2210,23 +2261,67 @@ mono_push_ephemerons (struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* ma
22102261 gpointer * handles = key ;
22112262 size_t length = (size_t )value ;
22122263 for (size_t i = 0 ; i < length ; ++ i ) {
2213- MonoObject * * handle = handles + i ;
2214- if (!* handle )
2264+ MonoObject * * handle = (MonoObject * * )(handles + i );
2265+ MonoObject * object = * handle ;
2266+
2267+ if (!object )
22152268 continue ;
22162269
2217- MonoObject * object = * handle ;
2270+ /* avoid objects we've already processed before */
2271+ if ((size_t )object & 1 )
2272+ continue ;
22182273
22192274 if (GC_is_marked (object )) {
2220- continue ;
2221- }
2222- else {
2275+ s_on_handle_found (s_on_handle_found_arg , object );
22232276
2224- mark_stack_ptr = GC_mark_and_push ( object , mark_stack_ptr , mark_stack_limit , handle );
2277+ * handle = ( MonoObject * )(( size_t ) object | 1 );
22252278 }
22262279 }
22272280 }
22282281 }
22292282
2283+ /* callback to allow client to process a batch of handles */
2284+ if (s_on_process ) {
2285+ MarkHandleData data ;
2286+ data .mark_stack_ptr = mark_stack_ptr ;
2287+ data .mark_stack_limit = mark_stack_limit ;
2288+ s_mark_data = & data ;
2289+ s_on_process (s_on_process_arg );
2290+ mark_stack_ptr = data .mark_stack_ptr ;
2291+ s_mark_data = NULL ;
2292+ }
2293+
2294+ /* mark all handles, as we want to keep all targets alive like a strong handle */
2295+ if (mark_stack_ptr_orig == mark_stack_ptr ) {
2296+ GHashTableIter iter ;
2297+ g_hash_table_iter_init (& iter , late_handles );
2298+
2299+ gpointer key ;
2300+ gpointer value ;
2301+
2302+ while (g_hash_table_iter_next (& iter , & key , & value )) {
2303+ /* process handles */
2304+ gpointer * handles = key ;
2305+ size_t length = (size_t )value ;
2306+ for (size_t i = 0 ; i < length ; ++ i ) {
2307+ MonoObject * * handle = (MonoObject * * )(handles + i );
2308+
2309+ /* remove the bit we set to indicate processing */
2310+ if ((size_t )* handle & 1 )
2311+ * handle = (MonoObject * )((size_t )* handle & ~(size_t )1 );
2312+
2313+ MonoObject * object = * handle ;
2314+ if (!object )
2315+ continue ;
2316+
2317+ mark_stack_ptr = GC_mark_and_push (object , mark_stack_ptr , mark_stack_limit , handle );
2318+ }
2319+ }
2320+ s_on_handle_found = NULL ;
2321+ s_on_process = NULL ;
2322+ s_on_threads_suspended = NULL ;
2323+ }
2324+
22302325
22312326 ephemeron_node * prev_node = NULL ;
22322327 ephemeron_node * current_node = NULL ;
0 commit comments