#include <mono/utils/mono-threads-coop.h>
#include "cominterop.h"
#include <mono/utils/w32api.h>
+#include <mono/utils/unlocked.h>
static void
get_default_field_value (MonoDomain* domain, MonoClassField *field, void *value, MonoError *error);
type_initialization_hash = g_hash_table_new (NULL, NULL);
blocked_thread_hash = g_hash_table_new (NULL, NULL);
mono_os_mutex_init_recursive (&ldstr_section);
+ mono_register_jit_icall (ves_icall_string_alloc, "ves_icall_string_alloc", mono_create_icall_signature ("object int"), FALSE);
}
void
int max_set = 0;
gsize *bitmap;
gsize default_bitmap [4] = {0};
- static gboolean gcj_inited = FALSE;
MonoGCDescriptor gc_descr;
- if (!gcj_inited) {
- mono_loader_lock ();
-
- mono_register_jit_icall (ves_icall_object_new_fast, "ves_icall_object_new_fast", mono_create_icall_signature ("object ptr"), FALSE);
- mono_register_jit_icall (ves_icall_string_alloc, "ves_icall_string_alloc", mono_create_icall_signature ("object int"), FALSE);
-
- gcj_inited = TRUE;
- mono_loader_unlock ();
- }
-
if (!klass->inited)
mono_class_init (klass);
sig = mono_method_signature (method);
hashes_count = sig->param_count + 4;
- hashes_start = (guint32 *)malloc (hashes_count * sizeof (guint32));
+ hashes_start = (guint32 *)g_malloc (hashes_count * sizeof (guint32));
hashes = hashes_start;
if (! MONO_CLASS_IS_INTERFACE (method->klass)) {
if (imt_builder [imt_slot] != NULL) {
entry->children = imt_builder [imt_slot]->children + 1;
if (entry->children == 1) {
- mono_stats.imt_slots_with_collisions++;
+ UnlockedIncrement (&mono_stats.imt_slots_with_collisions);
*imt_collisions_bitmap |= (1 << imt_slot);
}
} else {
entry->children = 0;
- mono_stats.imt_used_slots++;
+ UnlockedIncrement (&mono_stats.imt_used_slots);
}
imt_builder [imt_slot] = entry;
#if DEBUG_IMT
MONO_REQ_GC_NEUTRAL_MODE;
int number_of_entries = entries->children + 1;
- MonoImtBuilderEntry **sorted_array = (MonoImtBuilderEntry **)malloc (sizeof (MonoImtBuilderEntry*) * number_of_entries);
+ MonoImtBuilderEntry **sorted_array = (MonoImtBuilderEntry **)g_malloc (sizeof (MonoImtBuilderEntry*) * number_of_entries);
GPtrArray *result = g_ptr_array_new ();
MonoImtBuilderEntry *current_entry;
int i;
int i;
GSList *list_item;
guint32 imt_collisions_bitmap = 0;
- MonoImtBuilderEntry **imt_builder = (MonoImtBuilderEntry **)calloc (MONO_IMT_SIZE, sizeof (MonoImtBuilderEntry*));
+ MonoImtBuilderEntry **imt_builder = (MonoImtBuilderEntry **)g_calloc (MONO_IMT_SIZE, sizeof (MonoImtBuilderEntry*));
int method_count = 0;
gboolean record_method_count_for_max_collisions = FALSE;
gboolean has_generic_virtual = FALSE, has_variant_iface = FALSE;
if (imt_builder [i] != NULL) {
int methods_in_slot = imt_builder [i]->children + 1;
- if (methods_in_slot > mono_stats.imt_max_collisions_in_slot) {
- mono_stats.imt_max_collisions_in_slot = methods_in_slot;
+ if (methods_in_slot > UnlockedRead (&mono_stats.imt_max_collisions_in_slot)) {
+ UnlockedWrite (&mono_stats.imt_max_collisions_in_slot, methods_in_slot);
record_method_count_for_max_collisions = TRUE;
}
method_count += methods_in_slot;
}
}
- mono_stats.imt_number_of_methods += method_count;
+ UnlockedAdd (&mono_stats.imt_number_of_methods, method_count);
if (record_method_count_for_max_collisions) {
- mono_stats.imt_method_count_when_max_collisions = method_count;
+ UnlockedWrite (&mono_stats.imt_method_count_when_max_collisions, method_count);
}
for (i = 0; i < MONO_IMT_SIZE; i++) {
if (klass->interface_offsets_count) {
imt_table_bytes = sizeof (gpointer) * (MONO_IMT_SIZE);
- mono_stats.imt_number_of_tables++;
- mono_stats.imt_tables_size += imt_table_bytes;
+ UnlockedIncrement (&mono_stats.imt_number_of_tables);
+ UnlockedAdd (&mono_stats.imt_tables_size, imt_table_bytes);
} else {
imt_table_bytes = 0;
}
vtable_size = imt_table_bytes + MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer);
- mono_stats.used_class_count++;
- mono_stats.class_vtable_size += vtable_size;
+ UnlockedIncrement (&mono_stats.used_class_count);
+ UnlockedAdd (&mono_stats.class_vtable_size, vtable_size);
interface_offsets = alloc_vtable (domain, vtable_size, imt_table_bytes);
vt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes);
vt->vtable [klass->vtable_size] = mono_domain_alloc0 (domain, class_size);
}
vt->has_static_fields = TRUE;
- mono_stats.class_static_data_size += class_size;
+ UnlockedAdd (&mono_stats.class_static_data_size, class_size);
}
iter = NULL;
}
#ifndef DISABLE_REMOTING
+/**
+ * mono_remote_class_is_interface_proxy:
+ * \param remote_class
+ *
+ * Returns TRUE if the given remote class is a proxying an interface (as
+ * opposed to a class deriving from MarshalByRefObject).
+ */
+gboolean
+mono_remote_class_is_interface_proxy (MonoRemoteClass *remote_class)
+{
+ /* This if condition is taking advantage of how mono_remote_class ()
+ * works: if that code changes, this needs to change too. */
+ return (remote_class->interface_count >= 1 &&
+ remote_class->proxy_class == mono_defaults.marshalbyrefobject_class);
+}
+
/**
* mono_class_proxy_vtable:
* \param domain the application domain
}
imt_table_bytes = sizeof (gpointer) * MONO_IMT_SIZE;
- mono_stats.imt_number_of_tables++;
- mono_stats.imt_tables_size += imt_table_bytes;
+ UnlockedIncrement (&mono_stats.imt_number_of_tables);
+ UnlockedAdd (&mono_stats.imt_tables_size, imt_table_bytes);
vtsize = imt_table_bytes + MONO_SIZEOF_VTABLE + klass->vtable_size * sizeof (gpointer);
- mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
+ UnlockedAdd (&mono_stats.class_vtable_size, vtsize + extra_interface_vtsize);
interface_offsets = alloc_vtable (domain, vtsize + extra_interface_vtsize, imt_table_bytes);
pvt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes);
/* we need to keep the GC descriptor for a transparent proxy or we confuse the precise GC */
pvt->gc_descr = mono_defaults.transparent_proxy_class->gc_descr;
+ if (mono_remote_class_is_interface_proxy (remote_class)) {
+ /* If it's a transparent proxy for an interface, set the
+ * MonoVTable:type to the interface type, not the placeholder
+ * MarshalByRefObject class. This is used when mini JITs calls
+ * to Object.GetType ()
+ */
+ MonoType *itf_proxy_type = &remote_class->interfaces[0]->byval_arg;
+ pvt->type = mono_type_get_object_checked (domain, itf_proxy_type, error);
+ if (!is_ok (error))
+ goto failure;
+ }
+
/* initialize vtable */
mono_class_setup_vtable (klass);
for (i = 0; i < klass->vtable_size; ++i) {
key = mp_key;
if (mono_class_is_interface (proxy_class)) {
+ /* If we need to proxy an interface, we use this stylized
+ * representation (interface_count >= 1, proxy_class is
+ * MarshalByRefObject). The code in
+ * mono_remote_class_is_interface_proxy () depends on being
+ * able to detect that we're doing this, so if this
+ * representation changes, change GetType, too. */
rc = (MonoRemoteClass *)mono_domain_alloc (domain, MONO_SIZEOF_REMOTE_CLASS + sizeof(MonoClass*));
rc->interface_count = 1;
rc->interfaces [0] = proxy_class;
rc->xdomain_vtable = NULL;
rc->proxy_class_name = name;
#ifndef DISABLE_PERFCOUNTERS
- mono_perfcounters->loader_bytes += mono_string_length (MONO_HANDLE_RAW (class_name)) + 1;
+ InterlockedAdd (&mono_perfcounters->loader_bytes, mono_string_length (MONO_HANDLE_RAW (class_name)) + 1);
#endif
g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
MonoObjectHandle current_appdomain_delegate = MONO_HANDLE_NEW (MonoObject, NULL);
MonoClass *klass = mono_handle_class (exc);
- if (mono_class_has_parent (klass, mono_defaults.threadabortexception_class))
+ /*
+ * AppDomainUnloadedException don't behave like unhandled exceptions unless thrown from
+ * a thread started in unmanaged world.
+ * https://msdn.microsoft.com/en-us/library/system.appdomainunloadedexception(v=vs.110).aspx#Anchor_6
+ */
+ if (klass == mono_defaults.threadabortexception_class ||
+ (klass == mono_class_get_appdomain_unloaded_exception_class () &&
+ mono_thread_info_current ()->runtime_thread))
return;
field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "UnhandledException");
MonoVTable *vtable;
- vtable = mono_class_vtable (domain, klass);
- g_assert (vtable); /* FIXME don't swallow the error */
+ vtable = mono_class_vtable_full (domain, klass, error);
+ if (!is_ok (error))
+ return NULL;
MonoObject *o = mono_object_new_specific_checked (vtable, error);
return o;
return o;
}
-MonoObject *
-ves_icall_object_new_fast (MonoVTable *vtable)
-{
- MonoError error;
- MonoObject *o = mono_object_new_fast_checked (vtable, &error);
- mono_error_set_pending_exception (&error);
-
- return o;
-}
-
MonoObject*
mono_object_new_mature (MonoVTable *vtable, MonoError *error)
{
return o;
}
-/**
- * mono_class_get_allocation_ftn:
- * \param vtable vtable
- * \param for_box the object will be used for boxing
- * \param pass_size_in_words Unused
- * \returns the allocation function appropriate for the given class.
- */
-void*
-mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words)
-{
- MONO_REQ_GC_NEUTRAL_MODE;
-
- *pass_size_in_words = FALSE;
-
- if (mono_class_has_finalizer (vtable->klass) || mono_class_is_marshalbyref (vtable->klass))
- return ves_icall_object_new_specific;
-
- if (vtable->gc_descr != MONO_GC_DESCRIPTOR_NULL) {
-
- return ves_icall_object_new_fast;
-
- /*
- * FIXME: This is actually slower than ves_icall_object_new_fast, because
- * of the overhead of parameter passing.
- */
- /*
- *pass_size_in_words = TRUE;
-#ifdef GC_REDIRECT_TO_LOCAL
- return GC_local_gcj_fast_malloc;
-#else
- return GC_gcj_fast_malloc;
-#endif
- */
- }
-
- return ves_icall_object_new_specific;
-}
-
/**
* mono_object_new_from_token:
* \param image Context where the type_token is hosted
eh_callbacks.mono_raise_exception (ex);
}
+/**
+ * mono_raise_exception:
+ * \param ex exception object
+ * Signal the runtime that the exception \p ex has been raised in unmanaged code.
+ */
+void
+mono_reraise_exception (MonoException *ex)
+{
+ MONO_REQ_GC_UNSAFE_MODE;
+
+ /*
+ * NOTE: Do NOT annotate this function with G_GNUC_NORETURN, since
+ * that will cause gcc to omit the function epilog, causing problems when
+ * the JIT tries to walk the stack, since the return address on the stack
+ * will point into the next function in the executable, not this one.
+ */
+ eh_callbacks.mono_reraise_exception (ex);
+}
+
void
mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx)
{
static MonoObject*
mono_runtime_capture_context (MonoDomain *domain, MonoError *error)
{
+#ifdef HOST_WASM
+ return mono_runtime_invoke_checked (mono_get_context_capture_method (), NULL, NULL, error);
+#else
MONO_REQ_GC_UNSAFE_MODE;
RuntimeInvokeFunction runtime_invoke;
runtime_invoke = (RuntimeInvokeFunction)domain->capture_context_runtime_invoke;
return runtime_invoke (NULL, NULL, NULL, domain->capture_context_method);
+#endif
}
/**
* mono_async_result_new:
if (method)
MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method);
- mono_stats.delegate_creations++;
+ UnlockedIncrement (&mono_stats.delegate_creations);
#ifndef DISABLE_REMOTING
if (!MONO_HANDLE_IS_NULL (target) && mono_class_is_transparent_proxy (mono_handle_class (target))) {