#include <mono/utils/strenc.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-error-internals.h>
+#include <mono/utils/mono-memory-model.h>
#include "cominterop.h"
#ifdef HAVE_BOEHM_GC
MonoClass *klass = this->vtable->klass;
method = mono_class_get_method_from_name (klass, ".ctor", 0);
- g_assert (method);
+ if (!method)
+ g_error ("Could not lookup zero argument constructor for class %s", mono_type_get_full_name (klass));
if (method->klass->valuetype)
this = mono_object_unbox (this);
MonoException *ex;
gchar *full_name;
- g_assert (vtable->init_failed);
-
+ if (!vtable->init_failed)
+ g_error ("Trying to get the init exception for a non-failed vtable of class %s", mono_type_get_full_name (klass));
+
/*
* If the initializing thread was rudely aborted, the exception is not stored
* in the hash.
}
static gpointer
-default_delegate_trampoline (MonoClass *klass)
+default_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
{
g_assert_not_reached ();
return NULL;
gpointer
mono_runtime_create_delegate_trampoline (MonoClass *klass)
{
- return arch_create_delegate_trampoline (klass);
+ return arch_create_delegate_trampoline (mono_domain_get (), klass);
}
static MonoFreeMethodFunc default_mono_free_method = NULL;
hashes = hashes_start;
if (! MONO_CLASS_IS_INTERFACE (method->klass)) {
- printf ("mono_method_get_imt_slot: %s.%s.%s is not an interface MonoMethod\n",
+ g_error ("mono_method_get_imt_slot: %s.%s.%s is not an interface MonoMethod",
method->klass->name_space, method->klass->name, method->name);
- g_assert_not_reached ();
}
/* Initialize hashes */
char *t;
int i, vtable_slots;
int imt_table_bytes = 0;
+ int gc_bits;
guint32 vtable_size, class_size;
guint32 cindex;
gpointer iter;
#endif
vt->gc_descr = class->gc_descr;
+ gc_bits = mono_gc_get_vtable_bits (class);
+ g_assert (!(gc_bits & ~((1 << MONO_VTABLE_AVAILABLE_GC_BITS) - 1)));
+
+ vt->gc_bits = gc_bits;
+
if (class_size) {
/* we store the static field pointer at the end of the vtable: vt->vtable [class->vtable_size] */
if (class->has_static_refs) {
gsize default_bitmap [4] = {0};
gsize *bitmap;
int max_set = 0;
+ int numbits;
MonoClass *fclass;
if (mono_type_is_reference (field->type)) {
default_bitmap [0] = 1;
- max_set = 1;
+ numbits = 1;
bitmap = default_bitmap;
} else if (mono_type_is_struct (field->type)) {
fclass = mono_class_from_mono_type (field->type);
bitmap = compute_class_bitmap (fclass, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, FALSE);
+ numbits = max_set + 1;
} else {
default_bitmap [0] = 0;
- max_set = 0;
+ numbits = 0;
bitmap = default_bitmap;
}
size = mono_type_size (field->type, &align);
- offset = mono_alloc_special_static_data (special_static, size, align, (uintptr_t*)bitmap, max_set);
+ offset = mono_alloc_special_static_data (special_static, size, align, (uintptr_t*)bitmap, numbits);
if (!domain->special_static_fields)
domain->special_static_fields = g_hash_table_new (NULL, NULL);
g_hash_table_insert (domain->special_static_fields, field, GUINT_TO_POINTER (offset));
}
}
+ /* Initialize vtable */
+ if (callbacks.get_vtable_trampoline) {
+ // This also covers the AOT case
+ for (i = 0; i < class->vtable_size; ++i) {
+ vt->vtable [i] = callbacks.get_vtable_trampoline (i);
+ }
+ } else {
+ mono_class_setup_vtable (class);
+
+ for (i = 0; i < class->vtable_size; ++i) {
+ MonoMethod *cm;
+
+ if ((cm = class->vtable [i]))
+ vt->vtable [i] = arch_create_jit_trampoline (cm);
+ }
+ }
+
+ if (ARCH_USE_IMT && imt_table_bytes) {
+ /* Now that the vtable is full, we can actually fill up the IMT */
+ if (callbacks.get_imt_trampoline) {
+ /* lazy construction of the IMT entries enabled */
+ for (i = 0; i < MONO_IMT_SIZE; ++i)
+ interface_offsets [i] = callbacks.get_imt_trampoline (i);
+ } else {
+ build_imt (class, vt, domain, interface_offsets, NULL);
+ }
+ }
+
+ /*
+ * FIXME: Is it ok to allocate while holding the domain/loader locks ? If not, we can release them, allocate, then
+ * re-acquire them and check if another thread has created the vtable in the meantime.
+ */
+ /* Special case System.MonoType to avoid infinite recursion */
+ if (class != mono_defaults.monotype_class) {
+ /*FIXME check for OOM*/
+ vt->type = mono_type_get_object (domain, &class->byval_arg);
+ if (mono_object_get_class (vt->type) != mono_defaults.monotype_class)
+ /* This is unregistered in
+ unregister_vtable_reflection_type() in
+ domain.c. */
+ MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
+ }
+
+ if (class->contextbound)
+ vt->remote = 1;
+ else
+ vt->remote = 0;
+
/* class_vtable_array keeps an array of created vtables
*/
g_ptr_array_add (domain->class_vtable_array, vt);
* it it enlarged and when it is stored info.
*/
+ /*
+ * Store the vtable in class->runtime_info.
+ * class->runtime_info is accessed without locking, so this do this last after the vtable has been constructed.
+ */
+ mono_memory_barrier ();
+
old_info = class->runtime_info;
if (old_info && old_info->max_domain >= domain->domain_id) {
/* someone already created a large enough runtime info */
- mono_memory_barrier ();
old_info->domain_vtables [domain->domain_id] = vt;
} else {
int new_size = domain->domain_id;
class->runtime_info = runtime_info;
}
- /* Initialize vtable */
- if (callbacks.get_vtable_trampoline) {
- // This also covers the AOT case
- for (i = 0; i < class->vtable_size; ++i) {
- vt->vtable [i] = callbacks.get_vtable_trampoline (i);
- }
- } else {
- mono_class_setup_vtable (class);
-
- for (i = 0; i < class->vtable_size; ++i) {
- MonoMethod *cm;
-
- if ((cm = class->vtable [i]))
- vt->vtable [i] = arch_create_jit_trampoline (cm);
- }
- }
-
- if (ARCH_USE_IMT && imt_table_bytes) {
- /* Now that the vtable is full, we can actually fill up the IMT */
- if (callbacks.get_imt_trampoline) {
- /* lazy construction of the IMT entries enabled */
- for (i = 0; i < MONO_IMT_SIZE; ++i)
- interface_offsets [i] = callbacks.get_imt_trampoline (i);
- } else {
- build_imt (class, vt, domain, interface_offsets, NULL);
- }
+ if (class == mono_defaults.monotype_class) {
+ /*FIXME check for OOM*/
+ vt->type = mono_type_get_object (domain, &class->byval_arg);
+ if (mono_object_get_class (vt->type) != mono_defaults.monotype_class)
+ /* This is unregistered in
+ unregister_vtable_reflection_type() in
+ domain.c. */
+ MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
}
mono_domain_unlock (domain);
if (class->parent)
mono_class_vtable_full (domain, class->parent, raise_on_error);
- /*FIXME check for OOM*/
- vt->type = mono_type_get_object (domain, &class->byval_arg);
- if (mono_object_get_class (vt->type) != mono_defaults.monotype_class)
- /* This is unregistered in
- unregister_vtable_reflection_type() in
- domain.c. */
- MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
- if (class->contextbound)
- vt->remote = 1;
- else
- vt->remote = 0;
-
return vt;
}
rc->default_vtable = NULL;
rc->xdomain_vtable = NULL;
rc->proxy_class_name = name;
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->loader_bytes += mono_string_length (class_name) + 1;
+#endif
g_hash_table_insert (domain->proxy_vtable_hash, key, rc);
MonoClass *klass;
type = ((MonoReflectionType *)rp->class_to_proxy)->type;
klass = mono_class_from_mono_type (type);
+#ifndef DISABLE_COM
if ((klass->is_com_object || (mono_defaults.com_object_class && klass == mono_defaults.com_object_class)) && !mono_class_vtable (mono_domain_get (), klass)->remote)
remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_COMINTEROP);
else
+#endif
remote_class->default_vtable = mono_class_proxy_vtable (domain, remote_class, MONO_REMOTING_TARGET_UNKNOWN);
}
t = type->data.generic_class->container_class->byval_arg.type;
goto handle_enum;
default:
- g_warning ("got type %x", type->type);
- g_assert_not_reached ();
+ g_error ("got type %x", type->type);
}
}
mono_nullable_init (guint8 *buf, MonoObject *value, MonoClass *klass)
{
MonoClass *param_class = klass->cast_class;
+
+ mono_class_setup_fields_locking (klass);
+ g_assert (klass->fields_inited);
g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
{
MonoClass *param_class = klass->cast_class;
+ mono_class_setup_fields_locking (klass);
+ g_assert (klass->fields_inited);
+
g_assert (mono_class_from_mono_type (klass->fields [0].type) == param_class);
g_assert (mono_class_from_mono_type (klass->fields [1].type) == mono_defaults.boolean_class);
mono_runtime_delegate_invoke (MonoObject *delegate, void **params, MonoObject **exc)
{
MonoMethod *im;
+ MonoClass *klass = delegate->vtable->klass;
- im = mono_get_delegate_invoke (delegate->vtable->klass);
- g_assert (im);
+ im = mono_get_delegate_invoke (klass);
+ if (!im)
+ g_error ("Could not lookup delegate invoke method for delegate %s", mono_type_get_full_name (klass));
return mono_runtime_invoke (im, delegate, params, exc);
}
guint16 *ut;
glong items_written;
- ut = g_utf8_to_utf16 (text, length, NULL, &items_written, &error);
+ ut = eg_utf8_to_utf16_with_nuls (text, length, NULL, &items_written, &error);
if (!error)
o = mono_string_new_utf16 (domain, ut, items_written);
return obj;
} else {
MonoClass *oklass = vt->klass;
- if ((oklass == mono_defaults.transparent_proxy_class))
+ if (oklass == mono_defaults.transparent_proxy_class)
oklass = ((MonoTransparentProxy *)obj)->remote_class->proxy_class;
-
+
+ mono_class_setup_supertypes (klass);
if ((oklass->idepth >= klass->idepth) && (oklass->supertypes [klass->idepth - 1] == klass))
return obj;
}
* 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.
- */
-
- if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class) {
- MonoInternalThread *thread = mono_thread_internal_current ();
- g_assert (ex->object.vtable->domain == mono_domain_get ());
- MONO_OBJECT_SETREF (thread, abort_exc, ex);
- }
-
+ */
eh_callbacks.mono_raise_exception (ex);
}
void
mono_raise_exception_with_context (MonoException *ex, MonoContext *ctx)
{
- if (((MonoObject*)ex)->vtable->klass == mono_defaults.threadabortexception_class) {
- MonoInternalThread *thread = mono_thread_internal_current ();
- g_assert (ex->object.vtable->domain == mono_domain_get ());
- MONO_OBJECT_SETREF (thread, abort_exc, ex);
- }
-
eh_callbacks.mono_raise_exception_with_ctx (ex, ctx);
}
if (!object_array_klass) {
MonoClass *klass;
- klass = mono_array_class_get (mono_defaults.object_class, 1);
- g_assert (klass);
-
- mono_memory_barrier ();
- object_array_klass = klass;
-
klass = mono_array_class_get (mono_defaults.byte_class, 1);
g_assert (klass);
-
- mono_memory_barrier ();
byte_array_klass = klass;
klass = mono_array_class_get (mono_defaults.string_class, 1);
g_assert (klass);
-
- mono_memory_barrier ();
string_array_klass = klass;
+
+ klass = mono_array_class_get (mono_defaults.object_class, 1);
+ g_assert (klass);
+
+ mono_atomic_store_release (&object_array_klass, klass);
}
MONO_OBJECT_SETREF (this, method, method);
if (exc == (MonoObject*)mono_object_domain (exc)->out_of_memory_ex) {
message = g_strdup ("OutOfMemoryException");
+ free_message = TRUE;
} else {
- str = mono_object_to_string (exc, NULL);
- if (str) {
- message = mono_string_to_utf8_checked (str, &error);
- if (!mono_error_ok (&error)) {
- mono_error_cleanup (&error);
- message = (char *) "";
- } else {
- free_message = TRUE;
+
+ if (((MonoException*)exc)->native_trace_ips) {
+ message = mono_exception_get_native_backtrace ((MonoException*)exc);
+ free_message = TRUE;
+ } else {
+ str = mono_object_to_string (exc, NULL);
+ if (str) {
+ message = mono_string_to_utf8_checked (str, &error);
+ if (!mono_error_ok (&error)) {
+ mono_error_cleanup (&error);
+ message = (char *) "";
+ } else {
+ free_message = TRUE;
+ }
}
}
}
* g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
* exc->vtable->klass->name, message);
*/
- g_printerr ("\nUnhandled Exception: %s\n", message);
+ g_printerr ("\nUnhandled Exception:\n%s\n", message);
if (free_message)
g_free (message);
MONO_OBJECT_SETREF (delegate, target, target);
}
- delegate->invoke_impl = arch_create_delegate_trampoline (delegate->object.vtable->klass);
+ delegate->invoke_impl = arch_create_delegate_trampoline (delegate->object.vtable->domain, delegate->object.vtable->klass);
}
/**
g_assert (addr);
- if ((ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr)))) {
+ ji = mono_jit_info_table_find (domain, mono_get_addr_from_ftnptr (addr));
+ /* Shared code */
+ if (!ji && domain != mono_get_root_domain ())
+ ji = mono_jit_info_table_find (mono_get_root_domain (), mono_get_addr_from_ftnptr (addr));
+ if (ji) {
method = ji->method;
g_assert (!method->klass->generic_container);
}