#include "metadata/abi-details.h"
#include "metadata/mono-gc.h"
#include "metadata/runtime.h"
-#include "metadata/sgen-bridge-internal.h"
-#include "metadata/gc-internal.h"
+#include "metadata/sgen-bridge-internals.h"
+#include "metadata/gc-internals.h"
+#include "metadata/handle.h"
#include "utils/mono-memory-model.h"
-#include "utils/mono-logger-internal.h"
+#include "utils/mono-logger-internals.h"
#ifdef HEAVY_STATISTICS
static guint64 stat_wbarrier_set_arrayref = 0;
*/
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_LDPTR_NURSERY_START);
- mono_mb_emit_icon (mb, DEFAULT_NURSERY_BITS);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_NURSERY_BITS);
mono_mb_emit_byte (mb, CEE_SHR_UN);
mono_mb_emit_stloc (mb, shifted_nursery_start);
mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_icon (mb, DEFAULT_NURSERY_BITS);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_NURSERY_BITS);
mono_mb_emit_byte (mb, CEE_SHR_UN);
mono_mb_emit_ldloc (mb, shifted_nursery_start);
nursery_check_return_labels [0] = mono_mb_emit_branch (mb, CEE_BEQ);
// if (!ptr_in_nursery (*ptr)) return;
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icon (mb, DEFAULT_NURSERY_BITS);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_NURSERY_BITS);
mono_mb_emit_byte (mb, CEE_SHR_UN);
mono_mb_emit_ldloc (mb, shifted_nursery_start);
nursery_check_return_labels [1] = mono_mb_emit_branch (mb, CEE_BNE_UN);
MonoMethodBuilder *mb;
MonoMethodSignature *sig;
MonoMethod **write_barrier_method_addr;
+ WrapperInfo *info;
#ifdef MANAGED_WBARRIER
int i, nursery_check_labels [2];
#endif
#endif
#endif
res = mono_mb_create_method (mb, sig, 16);
+ info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
+ mono_marshal_set_wrapper_info (res, info);
mono_mb_free (mb);
LOCK_GC;
klass.element_class = mono_defaults.byte_class;
klass.rank = 1;
- klass.instance_size = sizeof (MonoArray);
+ klass.instance_size = MONO_SIZEOF_MONO_ARRAY;
klass.sizes.element_size = 1;
klass.name = "array_filler_type";
{
MonoArray *o;
- if (size < sizeof (MonoArray)) {
+ if (size < MONO_SIZEOF_MONO_ARRAY) {
memset (start, 0, size);
return FALSE;
}
o = (MonoArray*)start;
o->obj.vtable = (MonoVTable*)get_array_fill_vtable ();
/* Mark this as not a real object */
- o->obj.synchronisation = GINT_TO_POINTER (-1);
+ o->obj.synchronisation = (MonoThreadsSync *)GINT_TO_POINTER (-1);
o->bounds = NULL;
- o->max_length = (mono_array_size_t)(size - sizeof (MonoArray));
+ o->max_length = (mono_array_size_t)(size - MONO_SIZEOF_MONO_ARRAY);
return TRUE;
}
void
sgen_client_zero_array_fill_header (void *p, size_t size)
{
- if (size >= sizeof (MonoArray)) {
- memset (p, 0, sizeof (MonoArray));
+ if (size >= MONO_SIZEOF_MONO_ARRAY) {
+ memset (p, 0, MONO_SIZEOF_MONO_ARRAY);
} else {
- static guint8 zeros [sizeof (MonoArray)];
+ static guint8 zeros [MONO_SIZEOF_MONO_ARRAY];
SGEN_ASSERT (0, !memcmp (p, zeros, size), "TLAB segment must be zeroed out.");
}
static MonoGCFinalizerCallbacks fin_callbacks;
guint
-mono_gc_get_vtable_bits (MonoClass *class)
+mono_gc_get_vtable_bits (MonoClass *klass)
{
guint res = 0;
/* FIXME move this to the bridge code */
if (sgen_need_bridge_processing ()) {
- switch (sgen_bridge_class_kind (class)) {
+ switch (sgen_bridge_class_kind (klass)) {
case GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS:
case GC_BRIDGE_OPAQUE_BRIDGE_CLASS:
res = SGEN_GC_BIT_BRIDGE_OBJECT;
}
}
if (fin_callbacks.is_class_finalization_aware) {
- if (fin_callbacks.is_class_finalization_aware (class))
+ if (fin_callbacks.is_class_finalization_aware (klass))
res |= SGEN_GC_BIT_FINALIZER_AWARE;
}
return res;
static gboolean
object_in_domain_predicate (MonoObject *obj, void *user_data)
{
- MonoDomain *domain = user_data;
+ MonoDomain *domain = (MonoDomain *)user_data;
if (mono_object_domain (obj) == domain) {
SGEN_LOG (5, "Unregistering finalizer for object: %p (%s)", obj, sgen_client_vtable_get_name (SGEN_LOAD_VTABLE (obj)));
return TRUE;
LOCK_GC;
- node = sgen_alloc_internal (INTERNAL_MEM_EPHEMERON_LINK);
+ node = (EphemeronLinkNode *)sgen_alloc_internal (INTERNAL_MEM_EPHEMERON_LINK);
if (!node) {
UNLOCK_GC;
return FALSE;
{
MonoObject *obj = sgen_alloc_obj (vtable, size);
- if (G_UNLIKELY (alloc_events))
- mono_profiler_allocation (obj);
+ if (G_UNLIKELY (alloc_events)) {
+ if (obj)
+ mono_profiler_allocation (obj);
+ }
return obj;
}
{
MonoObject *obj = sgen_alloc_obj_pinned (vtable, size);
- if (G_UNLIKELY (alloc_events))
- mono_profiler_allocation (obj);
+ if (G_UNLIKELY (alloc_events)) {
+ if (obj)
+ mono_profiler_allocation (obj);
+ }
return obj;
}
void*
-mono_gc_alloc_mature (MonoVTable *vtable)
+mono_gc_alloc_mature (MonoVTable *vtable, size_t size)
{
- MonoObject *obj = sgen_alloc_obj_mature (vtable, vtable->klass->instance_size);
+ MonoObject *obj = sgen_alloc_obj_mature (vtable, size);
- if (obj && G_UNLIKELY (obj->vtable->klass->has_finalize))
- mono_object_register_finalizer (obj);
-
- if (G_UNLIKELY (alloc_events))
- mono_profiler_allocation (obj);
+ if (G_UNLIKELY (alloc_events)) {
+ if (obj)
+ mono_profiler_allocation (obj);
+ }
return obj;
}
void *res = calloc (1, size);
if (!res)
return NULL;
- if (!mono_gc_register_root (res, size, descr, source, msg)) {
+ if (!mono_gc_register_root ((char *)res, size, descr, source, msg)) {
free (res);
res = NULL;
}
void
mono_gc_free_fixed (void* addr)
{
- mono_gc_deregister_root (addr);
+ mono_gc_deregister_root ((char *)addr);
free (addr);
}
static gboolean registered = FALSE;
int tlab_next_addr_var, new_next_var;
const char *name = NULL;
- AllocatorWrapperInfo *info;
+ WrapperInfo *info;
int num_params, i;
if (!registered) {
case ATYPE_NORMAL:
case ATYPE_SMALL:
mono_mb_emit_ldarg (mb, 0);
- mono_mb_emit_icall (mb, mono_object_new_specific);
+ mono_mb_emit_icall (mb, ves_icall_object_new_specific);
break;
case ATYPE_VECTOR:
mono_mb_emit_ldarg (mb, 0);
mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_icall (mb, mono_array_new_specific);
+ mono_mb_emit_icall (mb, ves_icall_array_new_specific);
break;
case ATYPE_STRING:
mono_mb_emit_ldarg (mb, 1);
- mono_mb_emit_icall (mb, mono_string_alloc);
+ mono_mb_emit_icall (mb, ves_icall_string_alloc);
break;
default:
g_assert_not_reached ();
mono_mb_patch_short_branch (mb, pos);
- clause = mono_image_alloc0 (mono_defaults.corlib, sizeof (MonoExceptionClause));
+ clause = (MonoExceptionClause *)mono_image_alloc0 (mono_defaults.corlib, sizeof (MonoExceptionClause));
clause->try_offset = mono_mb_get_label (mb);
/* vtable->klass->sizes.element_size */
mono_mb_emit_ldarg (mb, 1);
mono_mb_emit_byte (mb, CEE_MUL_OVF_UN);
/* + sizeof (MonoArray) */
- mono_mb_emit_icon (mb, sizeof (MonoArray));
+ mono_mb_emit_icon (mb, MONO_SIZEOF_MONO_ARRAY);
mono_mb_emit_byte (mb, CEE_ADD_OVF_UN);
mono_mb_emit_stloc (mb, size_var);
/* catch */
clause->flags = MONO_EXCEPTION_CLAUSE_NONE;
clause->try_len = mono_mb_get_pos (mb) - clause->try_offset;
- clause->data.catch_class = mono_class_from_name (mono_defaults.corlib,
+ clause->data.catch_class = mono_class_load_from_name (mono_defaults.corlib,
"System", "OverflowException");
- g_assert (clause->data.catch_class);
clause->handler_offset = mono_mb_get_label (mb);
- oom_exc_class = mono_class_from_name (mono_defaults.corlib,
+ oom_exc_class = mono_class_load_from_name (mono_defaults.corlib,
"System", "OutOfMemoryException");
- g_assert (oom_exc_class);
ctor = mono_class_get_method_from_name (oom_exc_class, ".ctor", 0);
g_assert (ctor);
mono_mb_emit_byte (mb, CEE_RET);
#endif
- res = mono_mb_create_method (mb, csig, 8);
- mono_mb_free (mb);
+ info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NONE);
+ info->d.alloc.gc_name = "sgen";
+ info->d.alloc.alloc_type = atype;
+
#ifndef DISABLE_JIT
- mono_method_get_header (res)->init_locals = FALSE;
+ mb->init_locals = FALSE;
#endif
- info = mono_image_alloc0 (mono_defaults.corlib, sizeof (AllocatorWrapperInfo));
- info->gc_name = "sgen";
- info->alloc_type = atype;
- mono_marshal_set_wrapper_info (res, info);
+ res = mono_mb_create (mb, csig, 8, info);
+ mono_mb_free (mb);
+
return res;
}
int
mono_gc_get_aligned_size_for_allocator (int size)
{
- int aligned_size = size;
- aligned_size += SGEN_ALLOC_ALIGN - 1;
- aligned_size &= ~(SGEN_ALLOC_ALIGN - 1);
- return aligned_size;
+ return SGEN_ALIGN_UP (size);
}
/*
MonoArray *arr = (MonoArray*)obj;
guint8 *card_data, *card_base;
guint8 *card_data_end;
- char *obj_start = sgen_card_table_align_pointer (obj);
+ char *obj_start = (char *)sgen_card_table_align_pointer (obj);
mword bounds_size;
mword obj_size = sgen_mono_array_size (vt, arr, &bounds_size, sgen_vtable_get_descriptor (vt));
/* We don't want to scan the bounds entries at the end of multidimensional arrays */
HEAVY_STAT (++los_array_cards);
for (; elem < card_end; elem += SIZEOF_VOID_P) {
- gpointer new, old = *(gpointer*)elem;
+ GCObject *new_;
+ gpointer old = *(gpointer*)elem;
if ((mod_union && old) || G_UNLIKELY (sgen_ptr_in_nursery (old))) {
HEAVY_STAT (++los_array_remsets);
copy_func ((GCObject**)elem, ctx.queue);
- new = *(gpointer*)elem;
- if (G_UNLIKELY (sgen_ptr_in_nursery (new)))
- sgen_add_to_global_remset (elem, new);
+ new_ = *(GCObject **)elem;
+ if (G_UNLIKELY (sgen_ptr_in_nursery (new_)))
+ sgen_add_to_global_remset (elem, new_);
}
}
}
arr = (MonoArray*)sgen_alloc_obj_nolock (vtable, size);
if (G_UNLIKELY (!arr)) {
UNLOCK_GC;
- return mono_gc_out_of_memory (size);
+ return NULL;
}
arr->max_length = (mono_array_size_t)max_length;
arr = (MonoArray*)sgen_alloc_obj_nolock (vtable, size);
if (G_UNLIKELY (!arr)) {
UNLOCK_GC;
- return mono_gc_out_of_memory (size);
+ return NULL;
}
arr->max_length = (mono_array_size_t)max_length;
str = (MonoString*)sgen_alloc_obj_nolock (vtable, size);
if (G_UNLIKELY (!str)) {
UNLOCK_GC;
- return mono_gc_out_of_memory (size);
+ return NULL;
}
str->length = len;
}
return;
case ROOT_DESC_COMPLEX: {
- gsize *bitmap_data = sgen_get_complex_descriptor_bitmap (desc);
+ gsize *bitmap_data = (gsize *)sgen_get_complex_descriptor_bitmap (desc);
gsize bwords = (*bitmap_data) - 1;
void **start_run = start_root;
bitmap_data++;
void **start_root;
RootRecord *root;
report.count = 0;
- SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], start_root, root) {
+ SGEN_HASH_TABLE_FOREACH (&roots_hash [root_type], void **, start_root, RootRecord *, root) {
SGEN_LOG (6, "Precise root scan %p-%p (desc: %p)", start_root, root->end_root, (void*)root->root_desc);
precisely_report_roots_from (&report, start_root, (void**)root->end_root, root->root_desc);
} SGEN_HASH_TABLE_FOREACH_END;
static void
walk_references (GCObject *start, size_t size, void *data)
{
- HeapWalkInfo *hwi = data;
+ HeapWalkInfo *hwi = (HeapWalkInfo *)data;
hwi->called = 0;
hwi->count = 0;
collect_references (hwi, start, size);
static void
sgen_thread_attach (SgenThreadInfo *info)
{
+ mono_handle_arena_init ((MonoHandleArena**) &info->client_info.info.handle_arena);
+
if (mono_gc_get_gc_callbacks ()->thread_attach_func && !info->client_info.runtime_data)
info->client_info.runtime_data = mono_gc_get_gc_callbacks ()->thread_attach_func ();
}
*/
if (mono_domain_get ())
mono_thread_detach_internal (mono_thread_internal_current ());
+
+ mono_handle_arena_cleanup ((MonoHandleArena**) &p->client_info.info.handle_arena);
}
gboolean
void
mono_gc_conservatively_scan_area (void *start, void *end)
{
- sgen_conservatively_pin_objects_from (start, end, scan_area_arg_start, scan_area_arg_end, PIN_TYPE_STACK);
+ sgen_conservatively_pin_objects_from ((void **)start, (void **)end, scan_area_arg_start, scan_area_arg_end, PIN_TYPE_STACK);
}
void*
mono_gc_scan_object (void *obj, void *gc_data)
{
- ScanCopyContext *ctx = gc_data;
+ ScanCopyContext *ctx = (ScanCopyContext *)gc_data;
ctx->ops->copy_or_mark_object ((GCObject**)&obj, ctx->queue);
return obj;
}
void
sgen_client_scan_thread_data (void *start_nursery, void *end_nursery, gboolean precise, ScanCopyContext ctx)
{
- SgenThreadInfo *info;
-
scan_area_arg_start = start_nursery;
scan_area_arg_end = end_nursery;
g_assert (info->client_info.suspend_done);
SGEN_LOG (3, "Scanning thread %p, range: %p-%p, size: %zd, pinned=%zd", info, info->client_info.stack_start, info->client_info.stack_end, (char*)info->client_info.stack_end - (char*)info->client_info.stack_start, sgen_get_pinned_count ());
if (mono_gc_get_gc_callbacks ()->thread_mark_func && !conservative_stack_mark) {
- mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, aligned_stack_start, info->client_info.stack_end, precise, &ctx);
+ mono_gc_get_gc_callbacks ()->thread_mark_func (info->client_info.runtime_data, (guint8 *)aligned_stack_start, (guint8 *)info->client_info.stack_end, precise, &ctx);
} else if (!precise) {
if (!conservative_stack_mark) {
fprintf (stderr, "Precise stack mark not supported - disabling.\n");
conservative_stack_mark = TRUE;
}
- sgen_conservatively_pin_objects_from (aligned_stack_start, info->client_info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
+ sgen_conservatively_pin_objects_from ((void **)aligned_stack_start, (void **)info->client_info.stack_end, start_nursery, end_nursery, PIN_TYPE_STACK);
}
if (!precise) {
#ifdef USE_MONO_CTX
- sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)&info->client_info.ctx + ARCH_NUM_REGS,
+ sgen_conservatively_pin_objects_from ((void**)&info->client_info.ctx, (void**)(&info->client_info.ctx + 1),
start_nursery, end_nursery, PIN_TYPE_STACK);
#else
sgen_conservatively_pin_objects_from ((void**)&info->client_info.regs, (void**)&info->client_info.regs + ARCH_NUM_REGS,
start_nursery, end_nursery, PIN_TYPE_STACK);
#endif
+ {
+ // This is used on Coop GC for platforms where we cannot get the data for individual registers.
+ // We force a spill of all registers into the stack and pass a chunk of data into sgen.
+ MonoThreadUnwindState *state = &info->client_info.info.thread_saved_state [SELF_SUSPEND_STATE_INDEX];
+ if (state && state->gc_stackdata) {
+ sgen_conservatively_pin_objects_from ((void **)state->gc_stackdata, (void**)((char*)state->gc_stackdata + state->gc_stackdata_size),
+ start_nursery, end_nursery, PIN_TYPE_STACK);
+ }
+ }
}
- } END_FOREACH_THREAD
+ } FOREACH_THREAD_END
}
/*
* @gchandle: a GCHandle's handle.
* @domain: An application domain.
*
- * Returns: true if the object wrapped by the @gchandle belongs to the specific @domain.
+ * Returns: TRUE if the object wrapped by the @gchandle belongs to the specific @domain.
*/
gboolean
mono_gchandle_is_in_domain (guint32 gchandle, MonoDomain *domain)
{
- MonoDomain *gchandle_domain = sgen_gchandle_get_metadata (gchandle);
+ MonoDomain *gchandle_domain = (MonoDomain *)sgen_gchandle_get_metadata (gchandle);
return domain->domain_id == gchandle_domain->domain_id;
}
static gpointer
null_link_if_in_domain (gpointer hidden, GCHandleType handle_type, int max_generation, gpointer user)
{
- MonoDomain *unloading_domain = user;
+ MonoDomain *unloading_domain = (MonoDomain *)user;
MonoDomain *obj_domain;
gboolean is_weak = MONO_GC_HANDLE_TYPE_IS_WEAK (handle_type);
if (MONO_GC_HANDLE_IS_OBJECT_POINTER (hidden)) {
- MonoObject *obj = MONO_GC_REVEAL_POINTER (hidden, is_weak);
+ MonoObject *obj = (MonoObject *)MONO_GC_REVEAL_POINTER (hidden, is_weak);
obj_domain = mono_object_domain (obj);
} else {
- obj_domain = MONO_GC_REVEAL_POINTER (hidden, is_weak);
+ obj_domain = (MonoDomain *)MONO_GC_REVEAL_POINTER (hidden, is_weak);
}
if (unloading_domain->domain_id == obj_domain->domain_id)
return NULL;
{
guint type;
for (type = HANDLE_TYPE_MIN; type < HANDLE_TYPE_MAX; ++type)
- sgen_gchandle_iterate (type, GENERATION_OLD, null_link_if_in_domain, domain);
+ sgen_gchandle_iterate ((GCHandleType)type, GENERATION_OLD, null_link_if_in_domain, domain);
}
void
mono_gc_wait_for_bridge_processing ();
}
-gboolean
-mono_gc_set_allow_synchronous_major (gboolean flag)
-{
- return sgen_set_allow_synchronous_major (flag);
-}
-
void*
mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data)
{
// FIXME:
}
-void
-sgen_client_out_of_memory (size_t size)
-{
- mono_gc_out_of_memory (size);
-}
-
guint8*
mono_gc_get_card_table (int *shift_bits, gpointer *mask)
{
static int last_major_gc_warned = -1;
static int num_degraded = 0;
- if (last_major_gc_warned < gc_stats.major_gc_count) {
+ if (last_major_gc_warned < (int)gc_stats.major_gc_count) {
++num_degraded;
if (num_degraded == 1 || num_degraded == 3)
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_GC, "Warning: Degraded allocation. Consider increasing nursery-size if the warning persists.");
cb.thread_detach = sgen_thread_detach;
cb.thread_unregister = sgen_thread_unregister;
cb.thread_attach = sgen_thread_attach;
- cb.mono_method_is_critical = (gpointer)is_critical_method;
+ cb.mono_method_is_critical = (gboolean (*)(void *))is_critical_method;
cb.mono_thread_in_critical_region = thread_in_critical_region;
mono_threads_init (&cb, sizeof (SgenThreadInfo));
if (!strcmp (opt, "xdomain-checks")) {
sgen_mono_xdomain_checks = TRUE;
} else if (!strcmp (opt, "do-not-finalize")) {
- do_not_finalize = TRUE;
+ mono_do_not_finalize = TRUE;
+ } else if (g_str_has_prefix (opt, "do-not-finalize=")) {
+ opt = strchr (opt, '=') + 1;
+ mono_do_not_finalize = TRUE;
+ mono_do_not_finalize_class_names = g_strsplit (opt, ",", 0);
} else if (!strcmp (opt, "log-finalizers")) {
log_finalizers = TRUE;
} else if (!strcmp (opt, "no-managed-allocator")) {
if (nursery_canaries_enabled ())
sgen_set_use_managed_allocator (FALSE);
+
+#if defined(HAVE_KW_THREAD)
+ /* This can happen with using libmonosgen.so */
+ if (mono_tls_key_get_offset (TLS_KEY_SGEN_TLAB_NEXT_ADDR) == -1)
+ sgen_set_use_managed_allocator (FALSE);
+#endif
}
void