Skip to content

Commit fb16c90

Browse files
jonchamUnityAlex
authored andcommitted
Scan arrays precisely for references (case 1054493)
1 parent eeb6b4a commit fb16c90

File tree

1 file changed

+50
-3
lines changed

1 file changed

+50
-3
lines changed

mono/metadata/boehm-gc.c

+50-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#if HAVE_BOEHM_GC
4646

4747
#define GC_dirty(x)
48+
#include <private/gc_pmark.h>
49+
#include <gc_vector.h>
4850

4951
#if defined(HOST_DARWIN) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
5052
void *pthread_get_stackaddr_np(pthread_t);
@@ -112,6 +114,45 @@ static void on_gc_notification (GC_EventType event);
112114
// GC_word here to precisely match Boehm. Not size_t, not gsize.
113115
static void on_gc_heap_resize (GC_word new_size);
114116

117+
#define ELEMENT_CHUNK_SIZE 256
118+
#define VECTOR_PROC_INDEX 6
119+
static mse * GC_gcj_vector_proc (word * addr, mse * mark_stack_ptr,
120+
mse * mark_stack_limit, word env)
121+
{
122+
MonoArray* a = NULL;
123+
if (env)
124+
{
125+
g_assert (env == 1);
126+
127+
a = (MonoArray*)GC_base (addr);
128+
} else {
129+
g_assert (addr == GC_base (addr));
130+
131+
a = (MonoArray*)addr;
132+
}
133+
134+
if (!a->max_length)
135+
return mark_stack_ptr;
136+
137+
mono_array_size_t length = a->max_length;
138+
MonoClass* array_type = a->obj.vtable->klass;
139+
MonoClass *element_type = array_type->element_class;
140+
GC_descr element_desc = element_type->gc_descr;
141+
142+
g_assert ((element_desc & GC_DS_TAGS) == GC_DS_BITMAP);
143+
g_assert (element_type->valuetype);
144+
145+
int words_per_element = array_type->sizes.element_size / BYTES_PER_WORD;
146+
word *actual_start = (word *)a->vector;
147+
148+
/* start at first element or resume from last iteration */
149+
word *start = env ? addr : actual_start;
150+
/* end at last element or max chunk size */
151+
word *actual_end = actual_start + length * words_per_element;
152+
153+
return GC_gcj_vector_mark_proc (mark_stack_ptr, element_desc, start, actual_end, words_per_element);
154+
}
155+
115156
void
116157
mono_gc_base_init (void)
117158
{
@@ -163,6 +204,7 @@ mono_gc_base_init (void)
163204
GC_set_finalizer_notifier(mono_gc_finalize_notify);
164205

165206
GC_init_gcj_malloc (5, NULL);
207+
GC_init_gcj_vector (VECTOR_PROC_INDEX, GC_gcj_vector_proc);
166208
GC_allow_register_threads ();
167209

168210
params_opts = mono_gc_params_get();
@@ -722,7 +764,9 @@ mono_gc_make_descr_for_object (gsize *bitmap, int numbits, size_t obj_size)
722764
void*
723765
mono_gc_make_descr_for_array (int vector, gsize *elem_bitmap, int numbits, size_t elem_size)
724766
{
725-
/* libgc has no usable support for arrays... */
767+
/* libgc has no usable support for arrays...
768+
* but Unity added support with newer bdwgc
769+
* we don't need descriptor though, as arrays have custom mark proc */
726770
return GC_NO_DESCRIPTOR;
727771
}
728772

@@ -821,8 +865,11 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
821865
obj->obj.synchronisation = NULL;
822866

823867
memset (mono_object_get_data ((MonoObject*)obj), 0, size - MONO_ABI_SIZEOF (MonoObject));
824-
} else if (vtable->gc_descr != GC_NO_DESCRIPTOR) {
825-
obj = (MonoArray *)GC_GCJ_MALLOC (size, vtable);
868+
} else if (vtable->klass->element_class->valuetype &&
869+
vtable->klass->element_class->gc_descr != GC_NO_DESCRIPTOR &&
870+
vtable->domain == mono_get_root_domain () /* &&
871+
max_length > 50 */) {
872+
obj = (MonoArray *)GC_gcj_vector_malloc (size, vtable);
826873
if (G_UNLIKELY (!obj))
827874
return NULL;
828875
} else {

0 commit comments

Comments
 (0)