Skip to content

Commit df5da38

Browse files
committed
Basic functionality working.
1 parent 154eb59 commit df5da38

File tree

3 files changed

+123
-7
lines changed

3 files changed

+123
-7
lines changed

mono/metadata/boehm-gc.c

Lines changed: 102 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ static GHashTable* late_handles;
6969
typedef struct ephemeron_node ephemeron_node;
7070
static 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+
7279
static void
7380
mono_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+
21972246
static struct GC_ms_entry*
21982247
mono_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;

mono/metadata/object.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,20 @@ MONO_API MONO_RT_EXTERNAL_ONLY MonoGCHandle mono_gchandle_new_weakref_v2 (MonoOb
381381
MONO_API MONO_RT_EXTERNAL_ONLY MonoObject* mono_gchandle_get_target_v2 (MonoGCHandle gchandle);
382382
MONO_API MONO_RT_EXTERNAL_ONLY void mono_gchandle_free_v2 (MonoGCHandle gchandle);
383383

384+
385+
typedef void (*DoUnityProcessing)(void* handle);
386+
typedef void (*LateHandleCallback)(MonoObject* obj, void* user_data);
387+
388+
typedef void (*OnThreadsSuspendedCallback)(void* arg);
389+
typedef void (*OnHandleFoundCallback)(void* arg, void* handle);
390+
typedef void (*OnProcessCallback)(void* arg);
391+
MONO_API MONO_RT_EXTERNAL_ONLY void mono_gc_collect_assets(
392+
OnThreadsSuspendedCallback onThreadsSuspended, void* onThreadsSuspendedArg,
393+
OnHandleFoundCallback onHandleFound, void* onHandleFoundArg,
394+
OnProcessCallback onProcess, void* onProcessArg);
395+
396+
MONO_API MONO_RT_EXTERNAL_ONLY void mono_gchandle_mark_object(MonoObject* obj);
397+
384398
/* make sure the gchandle was allocated for an object in domain */
385399
UNITY_MONO_API MONO_RT_EXTERNAL_ONLY mono_bool mono_gchandle_is_in_domain_v2 (MonoGCHandle gchandle, MonoDomain* domain);
386400

mono/metadata/sgen-mono.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,6 +2781,13 @@ mono_gchandle_new_internal (MonoObject *obj, gboolean pinned)
27812781
return MONO_GC_HANDLE_FROM_UINT (sgen_gchandle_new (obj, pinned));
27822782
}
27832783

2784+
MonoGCHandle
2785+
mono_gchandle_new_late_internal(MonoObject* obj)
2786+
{
2787+
g_assert_not_reached ();
2788+
return 0;
2789+
}
2790+
27842791
/**
27852792
* mono_gchandle_new_weakref_internal:
27862793
* \param obj managed object to get a handle for

0 commit comments

Comments
 (0)