void sgen_client_init (void);
+/*
+ * Returns the vtable used for dummy objects to fill the nursery for ease and speed of
+ * walking. Must be a valid vtable that is not used by any actual objects. Must be
+ * idempotent.
+ */
+MonoVTable* sgen_client_get_array_fill_vtable (void);
+
+/*
+ * Fill the given range with a dummy object. Its vtable must be the one returned by
+ * `sgen_client_get_array_fill_vtable()`. If the range is too short to be filled with an
+ * object, null it. Return `TRUE` if the range was filled with an object, `FALSE` if it was
+ * nulled.
+ */
+gboolean sgen_client_array_fill_range (char *start, size_t size);
+
/*
* Called after an object is enqueued for finalization. This is a very low-level callback.
* It should almost certainly be a NOP.
SGEN_TV_DECLARE (sgen_init_timestamp);
-#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
-
NurseryClearPolicy nursery_clear_policy = CLEAR_AT_TLAB_CREATION;
#define object_is_forwarded SGEN_OBJECT_IS_FORWARDED
static void *moved_objects [MOVED_OBJECTS_NUM];
static int moved_objects_idx = 0;
-/* Vtable of the objects used to fill out nursery fragments before a collection */
-static MonoVTable *array_fill_vtable;
-
#ifdef SGEN_DEBUG_INTERNAL_ALLOC
MonoNativeThreadId main_gc_thread = NULL;
#endif
void
sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags)
{
+ MonoVTable *array_fill_vtable = sgen_client_get_array_fill_vtable ();
+
while (start < end) {
size_t size;
char *obj;
if (do_dump_nursery_content) {
if (cur > hole_start)
SGEN_LOG (1, "HOLE [%p %p %d]", hole_start, cur, (int)(cur - hole_start));
- SGEN_LOG (1, "OBJ [%p %p %d %d %s %d]", cur, cur + size, (int)size, (int)ss, sgen_safe_name ((MonoObject*)cur), (gpointer)LOAD_VTABLE (cur) == sgen_get_array_fill_vtable ());
+ SGEN_LOG (1, "OBJ [%p %p %d %d %s %d]", cur, cur + size, (int)size, (int)ss, sgen_safe_name ((MonoObject*)cur), (gpointer)LOAD_VTABLE (cur) == sgen_client_get_array_fill_vtable ());
}
- if (nursery_canaries_enabled () && (MonoVTable*)SGEN_LOAD_VTABLE (cur) != array_fill_vtable) {
+ if (nursery_canaries_enabled () && (MonoVTable*)SGEN_LOAD_VTABLE (cur) != sgen_client_get_array_fill_vtable ()) {
CHECK_CANARY_FOR_OBJECT (cur);
CANARIFY_SIZE (size);
}
return nursery_clear_policy;
}
-MonoVTable*
-sgen_get_array_fill_vtable (void)
-{
- if (!array_fill_vtable) {
- static MonoClass klass;
- static char _vtable[sizeof(MonoVTable)+8];
- MonoVTable* vtable = (MonoVTable*) ALIGN_TO(_vtable, 8);
- gsize bmap;
-
- MonoDomain *domain = mono_get_root_domain ();
- g_assert (domain);
-
- klass.element_class = mono_defaults.byte_class;
- klass.rank = 1;
- klass.instance_size = sizeof (MonoArray);
- klass.sizes.element_size = 1;
- klass.name = "array_filler_type";
-
- vtable->klass = &klass;
- bmap = 0;
- vtable->gc_descr = mono_gc_make_descr_for_array (TRUE, &bmap, 0, 1);
- vtable->rank = 1;
-
- array_fill_vtable = vtable;
- }
- return array_fill_vtable;
-}
-
void
sgen_gc_lock (void)
{
char* sgen_nursery_alloc_get_upper_alloc_bound (void);
void* sgen_nursery_alloc (size_t size);
void* sgen_nursery_alloc_range (size_t size, size_t min_size, size_t *out_alloc_size);
-MonoVTable* sgen_get_array_fill_vtable (void);
gboolean sgen_can_alloc_size (size_t size);
void sgen_nursery_retire_region (void *address, ptrdiff_t size);
sgen_get_remset ()->wbarrier_object_copy (obj, src);
}
+#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1))
+
+/* Vtable of the objects used to fill out nursery fragments before a collection */
+static MonoVTable *array_fill_vtable;
+
+MonoVTable*
+sgen_client_get_array_fill_vtable (void)
+{
+ if (!array_fill_vtable) {
+ static MonoClass klass;
+ static char _vtable[sizeof(MonoVTable)+8];
+ MonoVTable* vtable = (MonoVTable*) ALIGN_TO(_vtable, 8);
+ gsize bmap;
+
+ MonoDomain *domain = mono_get_root_domain ();
+ g_assert (domain);
+
+ klass.element_class = mono_defaults.byte_class;
+ klass.rank = 1;
+ klass.instance_size = sizeof (MonoArray);
+ klass.sizes.element_size = 1;
+ klass.name = "array_filler_type";
+
+ vtable->klass = &klass;
+ bmap = 0;
+ vtable->gc_descr = mono_gc_make_descr_for_array (TRUE, &bmap, 0, 1);
+ vtable->rank = 1;
+
+ array_fill_vtable = vtable;
+ }
+ return array_fill_vtable;
+}
+
+gboolean
+sgen_client_array_fill_range (char *start, size_t size)
+{
+ MonoArray *o;
+
+ if (size < sizeof (MonoArray)) {
+ memset (start, 0, size);
+ return FALSE;
+ }
+
+ o = (MonoArray*)start;
+ o->obj.vtable = sgen_client_get_array_fill_vtable ();
+ /* Mark this as not a real object */
+ o->obj.synchronisation = GINT_TO_POINTER (-1);
+ o->bounds = NULL;
+ o->max_length = (mono_array_size_t)(size - sizeof (MonoArray));
+
+ return TRUE;
+}
+
static MonoGCFinalizerCallbacks fin_callbacks;
guint
#include "metadata/sgen-bridge.h"
#include "metadata/sgen-memory-governor.h"
#include "metadata/sgen-pinning.h"
+#include "metadata/sgen-client.h"
#include "metadata/mono-gc.h"
#include "metadata/method-builder.h"
#include "metadata/profiler-private.h"
void
sgen_clear_range (char *start, char *end)
{
- MonoArray *o;
size_t size = end - start;
if ((start && !end) || (start > end))
g_error ("Invalid range [%p %p]", start, end);
- if (size < sizeof (MonoArray)) {
- memset (start, 0, size);
- return;
+ if (sgen_client_array_fill_range (start, size)) {
+ sgen_set_nursery_scan_start (start);
+ SGEN_ASSERT (0, start + sgen_safe_object_get_size ((MonoObject*)start) == end, "Array fill produced wrong size");
}
-
- o = (MonoArray*)start;
- o->obj.vtable = sgen_get_array_fill_vtable ();
- /* Mark this as not a real object */
- o->obj.synchronisation = GINT_TO_POINTER (-1);
- o->bounds = NULL;
- o->max_length = (mono_array_size_t)(size - sizeof (MonoArray));
- sgen_set_nursery_scan_start (start);
- g_assert (start + sgen_safe_object_get_size ((MonoObject*)o) == end);
}
void