@@ -2194,10 +2194,37 @@ mono_clear_ephemerons (void)
21942194 }
21952195}
21962196
2197+ LateHandleCallback s_late_handle_callback ;
2198+ void * s_late_handle_callback_user_data ;
2199+
2200+ void
2201+ mono_gchandle_set_late_callback (LateHandleCallback late_handle_callback , void * user_data )
2202+ {
2203+ s_late_handle_callback = late_handle_callback ;
2204+ s_late_handle_callback_user_data = user_data ;
2205+
2206+ }
2207+
2208+ typedef struct {
2209+ struct GC_ms_entry * mark_stack_ptr ;
2210+ struct GC_ms_entry * mark_stack_limit ;
2211+ } MarkHandleData ;
2212+
2213+ MarkHandleData * s_mark_data ;
2214+
2215+
2216+ void mono_gchandle_mark_object (MonoObject * obj )
2217+ {
2218+ g_assert (s_mark_data );
2219+ s_mark_data -> mark_stack_ptr = GC_mark_and_push (obj , s_mark_data -> mark_stack_ptr , s_mark_data -> mark_stack_limit , NULL );
2220+ }
2221+
21972222static struct GC_ms_entry *
21982223mono_push_ephemerons (struct GC_ms_entry * mark_stack_ptr , struct GC_ms_entry * mark_stack_limit )
21992224{
2225+ struct GC_ms_entry * mark_stack_ptr_orig = mark_stack_ptr ;
22002226 /* push late GC handles */
2227+ if (s_late_handle_callback )
22012228 {
22022229 GHashTableIter iter ;
22032230 g_hash_table_iter_init (& iter , late_handles );
@@ -2217,14 +2244,42 @@ mono_push_ephemerons (struct GC_ms_entry* mark_stack_ptr, struct GC_ms_entry* ma
22172244 MonoObject * object = * handle ;
22182245
22192246 if (GC_is_marked (object )) {
2220- continue ;
2247+ MarkHandleData data ;
2248+ data .mark_stack_ptr = mark_stack_ptr ;
2249+ data .mark_stack_limit = mark_stack_limit ;
2250+ s_mark_data = & data ;
2251+ // optimize, only process newly marked object
2252+ s_late_handle_callback (object , s_late_handle_callback_user_data );
2253+ mark_stack_ptr = data .mark_stack_ptr ;
2254+ s_mark_data = NULL ;
22212255 }
2222- else {
2256+ }
2257+ }
2258+ }
22232259
2224- mark_stack_ptr = GC_mark_and_push (object , mark_stack_ptr , mark_stack_limit , handle );
2225- }
2260+ // mark all handles, as we want to keep all targets alive like a strong handle
2261+ if (mark_stack_ptr_orig == mark_stack_ptr )
2262+ {
2263+ GHashTableIter iter ;
2264+ g_hash_table_iter_init (& iter , late_handles );
2265+
2266+ gpointer key ;
2267+ gpointer value ;
2268+
2269+ while (g_hash_table_iter_next (& iter , & key , & value )) {
2270+ /* process handles */
2271+ gpointer * handles = key ;
2272+ size_t length = (size_t )value ;
2273+ for (size_t i = 0 ; i < length ; ++ i ) {
2274+ MonoObject * * handle = handles + i ;
2275+ if (!* handle )
2276+ continue ;
2277+
2278+ MonoObject * object = * handle ;
2279+ mark_stack_ptr = GC_mark_and_push (object , mark_stack_ptr , mark_stack_limit , handle );
22262280 }
22272281 }
2282+ s_late_handle_callback = NULL ;
22282283 }
22292284
22302285
0 commit comments