* Paolo Molaro (lupus@ximian.com)
*
* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
- * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
+ * Copyright 2001 Xamarin Inc (http://www.xamarin.com)
*/
#include <config.h>
#ifdef HAVE_ALLOCA_H
static MonoString*
mono_ldstr_metadata_sig (MonoDomain *domain, const char* sig);
+static void
+free_main_args (void);
+
+static char *
+mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error);
+
+
#define ldstr_lock() EnterCriticalSection (&ldstr_section)
#define ldstr_unlock() LeaveCriticalSection (&ldstr_section)
static CRITICAL_SECTION ldstr_section;
void
mono_thread_set_main (MonoThread *thread)
{
+ static gboolean registered = FALSE;
+
+ if (!registered) {
+ MONO_GC_REGISTER_ROOT_SINGLE (main_thread);
+ registered = TRUE;
+ }
+
main_thread = thread;
}
* mono_release_type_locks
*/
DeleteCriticalSection (&type_initialization_section);
+ g_hash_table_destroy (type_initialization_hash);
+ type_initialization_hash = NULL;
#endif
DeleteCriticalSection (&ldstr_section);
+ g_hash_table_destroy (blocked_thread_hash);
+ blocked_thread_hash = NULL;
+
+ free_main_args ();
}
/**
MonoVTable *module_vtable = mono_class_vtable_full (vtable->domain, module_klass, raise_exception);
if (!module_vtable)
return NULL;
- mono_runtime_class_init (module_vtable);
+ exc = mono_runtime_class_init_full (module_vtable, raise_exception);
+ if (exc)
+ return exc;
}
}
method = mono_class_get_cctor (klass);
g_hash_table_remove (type_initialization_hash, vtable);
g_free (lock);
}
+ mono_memory_barrier ();
if (!vtable->init_failed)
vtable->initialized = 1;
mono_type_initialization_unlock ();
}
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;
size = max_size;
}
+#ifdef HAVE_SGEN_GC
+ /*An Ephemeron cannot be marked by sgen*/
+ if (!static_fields && class->image == mono_defaults.corlib && !strcmp ("Ephemeron", class->name)) {
+ *max_set = 0;
+ memset (bitmap, 0, size / 8);
+ return bitmap;
+ }
+#endif
+
for (p = class; p != NULL; p = p->parent) {
gpointer iter = NULL;
while ((field = mono_class_get_fields (p, &iter))) {
return bitmap;
}
+/**
+ * mono_class_compute_bitmap:
+ *
+ * Mono internal function to compute a bitmap of reference fields in a class.
+ */
+gsize*
+mono_class_compute_bitmap (MonoClass *class, gsize *bitmap, int size, int offset, int *max_set, gboolean static_fields)
+{
+ return compute_class_bitmap (class, bitmap, size, offset, max_set, static_fields);
+}
+
#if 0
/*
* similar to the above, but sets the bits in the bitmap for any non-ref field
mono_class_compute_gc_descriptor (class->element_class);
if (!class->element_class->valuetype) {
gsize abm = 1;
- class->gc_descr = mono_gc_make_descr_for_array (TRUE, &abm, 1, sizeof (gpointer));
+ class->gc_descr = mono_gc_make_descr_for_array (class->byval_arg.type == MONO_TYPE_SZARRAY, &abm, 1, sizeof (gpointer));
/*printf ("new array descriptor: 0x%x for %s.%s\n", class->gc_descr,
class->name_space, class->name);*/
} else {
/* remove the object header */
bitmap = compute_class_bitmap (class->element_class, default_bitmap, sizeof (default_bitmap) * 8, - (int)(sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
- class->gc_descr = mono_gc_make_descr_for_array (TRUE, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
+ class->gc_descr = mono_gc_make_descr_for_array (class->byval_arg.type == MONO_TYPE_SZARRAY, bitmap, mono_array_element_size (class) / sizeof (gpointer), mono_array_element_size (class));
/*printf ("new vt array descriptor: 0x%x for %s.%s\n", class->gc_descr,
class->name_space, class->name);*/
if (bitmap != default_bitmap)
return SPECIAL_STATIC_NONE;
}
-static gpointer imt_trampoline = NULL;
-
-void
-mono_install_imt_trampoline (gpointer tramp_code)
-{
- imt_trampoline = tramp_code;
-}
-
#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
#define mix(a,b,c) { \
a -= c; a ^= rot(c, 4); c += b; \
* The IMT thunk might be called with an instance of one of the
* generic virtual methods, so has to fallback to the IMT trampoline.
*/
- imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], imt_trampoline);
+ imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], callbacks.get_imt_trampoline ? callbacks.get_imt_trampoline (i) : NULL);
} else {
imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], NULL);
}
mono_loader_lock (); /*FIXME build_imt_slots requires the loader lock.*/
mono_domain_lock (vtable->domain);
/* we change the slot only if it wasn't changed from the generic imt trampoline already */
- if (imt [imt_slot] == imt_trampoline)
+ if (imt [imt_slot] == callbacks.get_imt_trampoline (imt_slot))
build_imt_slots (vtable->klass, vtable, vtable->domain, imt, NULL, imt_slot);
mono_domain_unlock (vtable->domain);
mono_loader_unlock ();
p = mono_domain_code_reserve (domain, size);
*p = size;
+ mono_domain_lock (domain);
+ if (!domain->generic_virtual_thunks)
+ domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
+ g_hash_table_insert (domain->generic_virtual_thunks, p, p);
+ mono_domain_unlock (domain);
+
return p + 1;
}
{
guint32 *p = code;
MonoThunkFreeList *l = (MonoThunkFreeList*)(p - 1);
+ gboolean found = FALSE;
+ mono_domain_lock (domain);
+ if (!domain->generic_virtual_thunks)
+ domain->generic_virtual_thunks = g_hash_table_new (NULL, NULL);
+ if (g_hash_table_lookup (domain->generic_virtual_thunks, l))
+ found = TRUE;
+ mono_domain_unlock (domain);
+
+ if (!found)
+ /* Not allocated by mono_method_alloc_generic_virtual_thunk (), i.e. AOT */
+ return;
init_thunk_free_lists (domain);
while (domain->thunk_free_lists [0] && domain->thunk_free_lists [0]->length >= MAX_WAIT_LENGTH) {
if (++gvc->count == THUNK_THRESHOLD) {
gpointer *old_thunk = *vtable_slot;
- gpointer vtable_trampoline = callbacks.get_vtable_trampoline ? callbacks.get_vtable_trampoline ((gpointer*)vtable_slot - (gpointer*)vtable) : NULL;
+ gpointer vtable_trampoline = NULL;
+ gpointer imt_trampoline = NULL;
+
+ if ((gpointer)vtable_slot < (gpointer)vtable) {
+ int displacement = (gpointer*)vtable_slot - (gpointer*)vtable;
+ int imt_slot = MONO_IMT_SIZE + displacement;
- if ((gpointer)vtable_slot < (gpointer)vtable)
/* Force the rebuild of the thunk at the next call */
+ imt_trampoline = callbacks.get_imt_trampoline (imt_slot);
*vtable_slot = imt_trampoline;
- else {
+ } else {
+ vtable_trampoline = callbacks.get_vtable_trampoline ? callbacks.get_vtable_trampoline ((gpointer*)vtable_slot - (gpointer*)vtable->vtable) : NULL;
+
entries = get_generic_virtual_entries (domain, vtable_slot);
sorted = imt_sort_slot_entries (entries);
g_ptr_array_free (sorted, TRUE);
}
+#ifndef __native_client__
+ /* We don't re-use any thunks as there is a lot of overhead */
+ /* to deleting and re-using code in Native Client. */
if (old_thunk != vtable_trampoline && old_thunk != imt_trampoline)
invalidate_generic_virtual_thunk (domain, old_thunk);
+#endif
}
mono_domain_unlock (domain);
MonoClassRuntimeInfo *runtime_info, *old_info;
MonoClassField *field;
char *t;
- int i;
+ int i, vtable_slots;
int imt_table_bytes = 0;
+ int gc_bits;
guint32 vtable_size, class_size;
guint32 cindex;
gpointer iter;
if (!class->vtable_size)
mono_class_setup_vtable (class);
+ if (class->generic_class && !class->vtable)
+ mono_class_check_vtable_constraints (class, NULL);
+
+ /* Initialize klass->has_finalize */
+ mono_class_has_finalizer (class);
+
if (class->exception_type) {
mono_domain_unlock (domain);
mono_loader_unlock ();
return NULL;
}
+ vtable_slots = class->vtable_size;
+ /* we add an additional vtable slot to store the pointer to static field data only when needed */
+ class_size = mono_class_data_size (class);
+ if (class_size)
+ vtable_slots++;
+
if (ARCH_USE_IMT) {
- vtable_size = MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
+ vtable_size = MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer);
if (class->interface_offsets_count) {
imt_table_bytes = sizeof (gpointer) * (MONO_IMT_SIZE);
vtable_size += sizeof (gpointer) * (MONO_IMT_SIZE);
}
} else {
vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) +
- MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
+ MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer);
}
mono_stats.used_class_count++;
#endif
vt->gc_descr = class->gc_descr;
- if ((class_size = mono_class_data_size (class))) {
+ 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) {
gpointer statics_gc_descr;
int max_set = 0;
bitmap = compute_class_bitmap (class, default_bitmap, sizeof (default_bitmap) * 8, 0, &max_set, TRUE);
/*g_print ("bitmap 0x%x for %s.%s (size: %d)\n", bitmap [0], class->name_space, class->name, class_size);*/
statics_gc_descr = mono_gc_make_descr_from_bitmap (bitmap, max_set + 1);
- vt->data = mono_gc_alloc_fixed (class_size, statics_gc_descr);
- mono_domain_add_class_static_data (domain, class, vt->data, NULL);
+ vt->vtable [class->vtable_size] = mono_gc_alloc_fixed (class_size, statics_gc_descr);
+ mono_domain_add_class_static_data (domain, class, vt->vtable [class->vtable_size], NULL);
if (bitmap != default_bitmap)
g_free (bitmap);
} else {
- vt->data = mono_domain_alloc0 (domain, class_size);
+ vt->vtable [class->vtable_size] = mono_domain_alloc0 (domain, class_size);
}
+ vt->has_static_fields = TRUE;
mono_stats.class_static_data_size += class_size;
}
if (special_static != SPECIAL_STATIC_NONE) {
guint32 size, offset;
gint32 align;
+ gsize default_bitmap [4] = {0};
+ gsize *bitmap;
+ int max_set = 0;
+ MonoClass *fclass;
+ if (mono_type_is_reference (field->type)) {
+ default_bitmap [0] = 1;
+ max_set = 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);
+ } else {
+ default_bitmap [0] = 0;
+ max_set = 0;
+ bitmap = default_bitmap;
+ }
size = mono_type_size (field->type, &align);
- offset = mono_alloc_special_static_data (special_static, size, align);
+ offset = mono_alloc_special_static_data (special_static, size, align, (uintptr_t*)bitmap, max_set);
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));
+ if (bitmap != default_bitmap)
+ g_free (bitmap);
/*
* This marks the field as special static to speed up the
* checks in mono_field_static_get/set_value ().
const char *data = mono_field_get_data (field);
g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT));
- t = (char*)vt->data + field->offset;
+ t = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
/* some fields don't really have rva, they are just zeroed (bss? bug #343083) */
if (!data)
continue;
if (ARCH_USE_IMT && imt_table_bytes) {
/* Now that the vtable is full, we can actually fill up the IMT */
- if (imt_trampoline) {
+ if (callbacks.get_imt_trampoline) {
/* lazy construction of the IMT entries enabled */
for (i = 0; i < MONO_IMT_SIZE; ++i)
- interface_offsets [i] = imt_trampoline;
+ interface_offsets [i] = callbacks.get_imt_trampoline (i);
} else {
build_imt (class, vt, domain, interface_offsets, NULL);
}
/*FIXME check for OOM*/
vt->type = mono_type_get_object (domain, &class->byval_arg);
-#if HAVE_SGEN_GC
- if (mono_object_get_class (vt->type) != mono_defaults.monotype_class) {
- static void *type_desc = NULL;
-
- if (!type_desc) {
- gsize bmap = 1;
- type_desc = mono_gc_make_descr_from_bitmap (&bmap, 1);
- }
-
+ 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 ((char*)&vt->type, sizeof (gpointer), type_desc);
- }
-#endif
+ MONO_GC_REGISTER_ROOT_IF_MOVING(vt->type);
if (class->contextbound)
vt->remote = 1;
else
GSList *extra_interfaces = NULL;
MonoClass *class = remote_class->proxy_class;
gpointer *interface_offsets;
+ uint8_t *bitmap;
+ int bsize;
+
+#ifdef COMPRESSED_INTERFACE_BITMAP
+ int bcsize;
+#endif
vt = mono_class_vtable (domain, class);
g_assert (vt); /*FIXME property handle failure*/
}
pvt->max_interface_id = max_interface_id;
- pvt->interface_bitmap = mono_domain_alloc0 (domain, sizeof (guint8) * (max_interface_id/8 + 1 ));
+ bsize = sizeof (guint8) * (max_interface_id/8 + 1 );
+#ifdef COMPRESSED_INTERFACE_BITMAP
+ bitmap = g_malloc0 (bsize);
+#else
+ bitmap = mono_domain_alloc0 (domain, bsize);
+#endif
if (! ARCH_USE_IMT) {
/* initialize interface offsets */
}
for (i = 0; i < class->interface_offsets_count; ++i) {
int interface_id = class->interfaces_packed [i]->interface_id;
- pvt->interface_bitmap [interface_id >> 3] |= (1 << (interface_id & 7));
+ bitmap [interface_id >> 3] |= (1 << (interface_id & 7));
}
if (extra_interfaces) {
if (! ARCH_USE_IMT) {
interface_offsets [max_interface_id - interf->interface_id] = &pvt->vtable [slot];
}
- pvt->interface_bitmap [interf->interface_id >> 3] |= (1 << (interf->interface_id & 7));
+ bitmap [interf->interface_id >> 3] |= (1 << (interf->interface_id & 7));
iter = NULL;
j = 0;
}
}
+#ifdef COMPRESSED_INTERFACE_BITMAP
+ bcsize = mono_compress_bitmap (NULL, bitmap, bsize);
+ pvt->interface_bitmap = mono_domain_alloc0 (domain, bcsize);
+ mono_compress_bitmap (pvt->interface_bitmap, bitmap, bsize);
+ g_free (bitmap);
+#else
+ pvt->interface_bitmap = bitmap;
+#endif
return pvt;
}
return FALSE;
}
+/**
+ * mono_class_field_get_special_static_type:
+ * @field: The MonoClassField describing the field.
+ *
+ * Returns: SPECIAL_STATIC_THREAD if the field is thread static, SPECIAL_STATIC_CONTEXT if it is context static,
+ * SPECIAL_STATIC_NONE otherwise.
+ */
+guint32
+mono_class_field_get_special_static_type (MonoClassField *field)
+{
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
+ return SPECIAL_STATIC_NONE;
+ if (mono_field_is_deleted (field))
+ return SPECIAL_STATIC_NONE;
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_LITERAL))
+ return field_is_special_static (field->parent, field);
+ return SPECIAL_STATIC_NONE;
+}
+
/**
* mono_class_has_special_static_fields:
*
MonoClass *class = mono_class_from_mono_type (type);
int size = mono_class_value_size (class, NULL);
if (value == NULL)
- memset (dest, 0, size);
+ mono_gc_bzero (dest, size);
else
mono_gc_wbarrier_value_copy (dest, value, 1, class);
}
if (field->offset == -1) {
/* Special static */
- gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+ gpointer addr;
+
+ mono_domain_lock (vt->domain);
+ addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+ mono_domain_unlock (vt->domain);
dest = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
} else {
- dest = (char*)vt->data + field->offset;
+ dest = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
}
set_value (field->type, dest, value, FALSE);
}
-/* Used by the debugger */
+/**
+ * mono_vtable_get_static_field_data:
+ *
+ * Internal use function: return a pointer to the memory holding the static fields
+ * for a class or NULL if there are no static fields.
+ * This is exported only for use by the debugger.
+ */
void *
mono_vtable_get_static_field_data (MonoVTable *vt)
{
- return vt->data;
+ if (!vt->has_static_fields)
+ return NULL;
+ return vt->vtable [vt->klass->vtable_size];
}
static guint8*
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
if (field->offset == -1) {
/* Special static */
- gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+ gpointer addr;
+
+ mono_domain_lock (vt->domain);
+ addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+ mono_domain_unlock (vt->domain);
src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
} else {
- src = (guint8*)vt->data + field->offset;
+ src = (guint8*)mono_vtable_get_static_field_data (vt) + field->offset;
}
} else {
src = (guint8*)obj + field->offset;
{
void *src;
+ g_assert (obj);
+
g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
src = (char*)obj + field->offset;
gchar *v;
gboolean is_static = FALSE;
gboolean is_ref = FALSE;
+ gboolean is_literal = FALSE;
+ gboolean is_ptr = FALSE;
+ MonoError error;
+ MonoType *type = mono_field_get_type_checked (field, &error);
+
+ if (!mono_error_ok (&error))
+ mono_error_raise_exception (&error);
- switch (field->type->type) {
+ switch (type->type) {
case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
case MONO_TYPE_CLASS:
case MONO_TYPE_I8:
case MONO_TYPE_R8:
case MONO_TYPE_VALUETYPE:
- is_ref = field->type->byref;
+ is_ref = type->byref;
break;
case MONO_TYPE_GENERICINST:
- is_ref = !field->type->data.generic_class->container_class->valuetype;
+ is_ref = !mono_type_generic_inst_is_valuetype (type);
+ break;
+ case MONO_TYPE_PTR:
+ is_ptr = TRUE;
break;
default:
g_error ("type 0x%x not handled in "
- "mono_field_get_value_object", field->type->type);
+ "mono_field_get_value_object", type->type);
return NULL;
}
- if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
+ if (type->attrs & FIELD_ATTRIBUTE_LITERAL)
+ is_literal = TRUE;
+
+ if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
is_static = TRUE;
- vtable = mono_class_vtable (domain, field->parent);
- if (!vtable) {
- char *name = mono_type_get_full_name (field->parent);
- g_warning ("Could not retrieve the vtable for type %s in mono_field_get_value_object", name);
- g_free (name);
- return NULL;
+
+ if (!is_literal) {
+ vtable = mono_class_vtable (domain, field->parent);
+ if (!vtable) {
+ char *name = mono_type_get_full_name (field->parent);
+ /*FIXME extend this to use the MonoError api*/
+ g_warning ("Could not retrieve the vtable for type %s in mono_field_get_value_object", name);
+ g_free (name);
+ return NULL;
+ }
+ if (!vtable->initialized)
+ mono_runtime_class_init (vtable);
}
- if (!vtable->initialized)
- mono_runtime_class_init (vtable);
+ } else {
+ g_assert (obj);
}
if (is_ref) {
- if (is_static) {
+ if (is_literal) {
+ get_default_field_value (domain, field, &o);
+ } else if (is_static) {
mono_field_static_get_value (vtable, field, &o);
} else {
mono_field_get_value (obj, field, &o);
return o;
}
+ if (is_ptr) {
+ static MonoMethod *m;
+ gpointer args [2];
+ gpointer *ptr;
+ gpointer v;
+
+ if (!m) {
+ MonoClass *ptr_klass = mono_class_from_name_cached (mono_defaults.corlib, "System.Reflection", "Pointer");
+ m = mono_class_get_method_from_name_flags (ptr_klass, "Box", 2, METHOD_ATTRIBUTE_STATIC);
+ g_assert (m);
+ }
+
+ v = &ptr;
+ if (is_literal) {
+ get_default_field_value (domain, field, v);
+ } else if (is_static) {
+ mono_field_static_get_value (vtable, field, v);
+ } else {
+ mono_field_get_value (obj, field, v);
+ }
+
+ /* MONO_TYPE_PTR is passed by value to runtime_invoke () */
+ args [0] = *ptr;
+ args [1] = mono_type_get_object (mono_domain_get (), type);
+
+ return mono_runtime_invoke (m, NULL, args, NULL);
+ }
+
/* boxed value type */
- klass = mono_class_from_mono_type (field->type);
+ klass = mono_class_from_mono_type (type);
if (mono_class_is_nullable (klass))
return mono_nullable_box (mono_field_get_addr (obj, vtable, field), klass);
o = mono_object_new (domain, klass);
v = ((gchar *) o) + sizeof (MonoObject);
- if (is_static) {
+
+ if (is_literal) {
+ get_default_field_value (domain, field, v);
+ } else if (is_static) {
mono_field_static_get_value (vtable, field, v);
} else {
mono_field_get_value (obj, field, v);
mono_get_constant_value_from_blob (domain, def_type, data, value);
}
+void
+mono_field_static_get_value_for_thread (MonoInternalThread *thread, MonoVTable *vt, MonoClassField *field, void *value)
+{
+ void *src;
+
+ g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
+
+ if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
+ get_default_field_value (vt->domain, field, value);
+ return;
+ }
+
+ if (field->offset == -1) {
+ /* Special static */
+ gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
+ src = mono_get_special_static_data_for_thread (thread, GPOINTER_TO_UINT (addr));
+ } else {
+ src = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
+ }
+ set_value (field->type, value, src, TRUE);
+}
+
/**
* mono_field_static_get_value:
* @vt: vtable to the object
void
mono_field_static_get_value (MonoVTable *vt, MonoClassField *field, void *value)
{
- void *src;
-
- g_return_if_fail (field->type->attrs & FIELD_ATTRIBUTE_STATIC);
-
- if (field->type->attrs & FIELD_ATTRIBUTE_LITERAL) {
- get_default_field_value (vt->domain, field, value);
- return;
- }
-
- if (field->offset == -1) {
- /* Special static */
- gpointer addr = g_hash_table_lookup (vt->domain->special_static_fields, field);
- src = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
- } else {
- src = (char*)vt->data + field->offset;
- }
- set_value (field->type, value, src, TRUE);
+ return mono_field_static_get_value_for_thread (mono_thread_internal_current (), vt, field, value);
}
/**
if (param_class->has_references)
mono_gc_wbarrier_value_copy (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), 1, param_class);
else
- memcpy (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), mono_class_value_size (param_class, NULL));
+ mono_gc_memmove (buf + klass->fields [0].offset - sizeof (MonoObject), mono_object_unbox (value), mono_class_value_size (param_class, NULL));
} else {
- memset (buf + klass->fields [0].offset - sizeof (MonoObject), 0, mono_class_value_size (param_class, NULL));
+ mono_gc_bzero (buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
}
}
if (param_class->has_references)
mono_gc_wbarrier_value_copy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), 1, param_class);
else
- memcpy (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
+ mono_gc_memmove (mono_object_unbox (o), buf + klass->fields [0].offset - sizeof (MonoObject), mono_class_value_size (param_class, NULL));
return o;
}
else
* mono_get_delegate_invoke:
* @klass: The delegate class
*
- * Returns: the MonoMethod for the "Invoke" method in the delegate klass
+ * Returns: the MonoMethod for the "Invoke" method in the delegate klass or NULL if @klass is a broken delegate type
*/
MonoMethod *
mono_get_delegate_invoke (MonoClass *klass)
if (klass->exception_type)
return NULL;
im = mono_class_get_method_from_name (klass, "Invoke", -1);
- g_assert (im);
-
return im;
}
}
static void
-fire_process_exit_event (void)
+free_main_args (void)
{
- MonoClassField *field;
- MonoDomain *domain = mono_domain_get ();
- gpointer pa [2];
- MonoObject *delegate, *exc;
-
- field = mono_class_get_field_from_name (mono_defaults.appdomain_class, "ProcessExit");
- g_assert (field);
-
- if (domain != mono_get_root_domain ())
- return;
-
- delegate = *(MonoObject **)(((char *)domain->domain) + field->offset);
- if (delegate == NULL)
- return;
+ int i;
- pa [0] = domain;
- pa [1] = NULL;
- mono_runtime_delegate_invoke (delegate, pa, &exc);
+ for (i = 0; i < num_main_args; ++i)
+ g_free (main_args [i]);
+ g_free (main_args);
}
/**
MonoArray *args = NULL;
MonoDomain *domain = mono_domain_get ();
gchar *utf8_fullpath;
- int result;
+ MonoMethodSignature *sig;
g_assert (method != NULL);
}
argc--;
argv++;
- if (mono_method_signature (method)->param_count) {
+
+ sig = mono_method_signature (method);
+ if (!sig) {
+ g_print ("Unable to load Main method.\n");
+ exit (-1);
+ }
+
+ if (sig->param_count) {
args = (MonoArray*)mono_array_new (domain, mono_defaults.string_class, argc);
for (i = 0; i < argc; ++i) {
/* The encodings should all work, given that
mono_assembly_set_main (method->klass->image->assembly);
- result = mono_runtime_exec_main (method, args, exc);
- fire_process_exit_event ();
- return result;
+ return mono_runtime_exec_main (method, args, exc);
}
static MonoObject*
}
/* set exitcode only if we will abort the process */
- if (abort_process)
- mono_environment_exitcode_set (1);
if ((current_appdomain_delegate == NULL) && (root_appdomain_delegate == NULL)) {
+ if (abort_process)
+ mono_environment_exitcode_set (1);
mono_print_unhandled_exception (exc);
} else {
if (root_appdomain_delegate) {
}
}
-/*
+/**
+ * mono_runtime_exec_managed_code:
+ * @domain: Application domain
+ * @main_func: function to invoke from the execution thread
+ * @main_args: parameter to the main_func
+ *
* Launch a new thread to execute a function
*
* main_func is called back from the thread with main_args as the
if (!obj) {
obj = mono_object_new (mono_domain_get (), method->klass);
+ g_assert (obj); /*maybe we should raise a TLE instead?*/
if (mono_object_class(obj) == mono_defaults.transparent_proxy_class) {
method = mono_marshal_get_remoting_invoke (method->slot == -1 ? method : method->klass->vtable [method->slot]);
}
return mono_object_new_specific (vtable);
}
+/**
+ * mono_object_new_pinned:
+ *
+ * Same as mono_object_new, but the returned object will be pinned.
+ * For SGEN, these objects will only be freed at appdomain unload.
+ */
+MonoObject *
+mono_object_new_pinned (MonoDomain *domain, MonoClass *klass)
+{
+ MonoVTable *vtable;
+
+ MONO_ARCH_SAVE_REGS;
+ vtable = mono_class_vtable (domain, klass);
+ if (!vtable)
+ return NULL;
+
+#ifdef HAVE_SGEN_GC
+ return mono_gc_alloc_pinned_obj (vtable, mono_class_instance_size (klass));
+#else
+ return mono_object_new_specific (vtable);
+#endif
+}
+
/**
* mono_object_new_specific:
* @vtable: the vtable of the object that we want to create
if (!(mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
profile_allocs = FALSE;
- if (vtable->klass->has_finalize || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
+ if (mono_class_has_finalizer (vtable->klass) || vtable->klass->marshalbyref || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
return mono_object_new_specific;
if (!vtable->klass->has_references) {
MonoObject *o;
int size = obj->vtable->klass->instance_size;
+ if (obj->vtable->klass->rank)
+ return (MonoObject*)mono_array_clone ((MonoArray*)obj);
+
o = mono_object_allocate (size, obj->vtable);
if (obj->vtable->klass->has_references) {
} else {
int size = obj->vtable->klass->instance_size;
/* do not copy the sync state */
- memcpy ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
+ mono_gc_memmove ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
}
if (G_UNLIKELY (profile_allocs))
mono_profiler_allocation (o, obj->vtable->klass);
void
mono_array_full_copy (MonoArray *src, MonoArray *dest)
{
- mono_array_size_t size;
+ uintptr_t size;
MonoClass *klass = src->obj.vtable->klass;
MONO_ARCH_SAVE_REGS;
if (klass->element_class->has_references)
mono_value_copy_array (dest, 0, mono_array_addr_with_size (src, 0, 0), mono_array_length (src));
else
- memcpy (&dest->vector, &src->vector, size);
+ mono_gc_memmove (&dest->vector, &src->vector, size);
} else {
mono_array_memcpy_refs (dest, 0, src, 0, mono_array_length (src));
}
#else
- memcpy (&dest->vector, &src->vector, size);
+ mono_gc_memmove (&dest->vector, &src->vector, size);
#endif
}
mono_array_clone_in_domain (MonoDomain *domain, MonoArray *array)
{
MonoArray *o;
- mono_array_size_t size, i;
- mono_array_size_t *sizes;
+ uintptr_t size, i;
+ uintptr_t *sizes;
MonoClass *klass = array->obj.vtable->klass;
MONO_ARCH_SAVE_REGS;
if (klass->element_class->has_references)
mono_value_copy_array (o, 0, mono_array_addr_with_size (array, 0, 0), mono_array_length (array));
else
- memcpy (&o->vector, &array->vector, size);
+ mono_gc_memmove (&o->vector, &array->vector, size);
} else {
mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
}
#else
- memcpy (&o->vector, &array->vector, size);
+ mono_gc_memmove (&o->vector, &array->vector, size);
#endif
return o;
}
- sizes = alloca (klass->rank * sizeof(mono_array_size_t) * 2);
+ sizes = alloca (klass->rank * sizeof(intptr_t) * 2);
size = mono_array_element_size (klass);
for (i = 0; i < klass->rank; ++i) {
sizes [i] = array->bounds [i].length;
size *= array->bounds [i].length;
sizes [i + klass->rank] = array->bounds [i].lower_bound;
}
- o = mono_array_new_full (domain, klass, sizes, sizes + klass->rank);
+ o = mono_array_new_full (domain, klass, sizes, (intptr_t*)sizes + klass->rank);
#ifdef HAVE_SGEN_GC
if (klass->element_class->valuetype) {
if (klass->element_class->has_references)
mono_value_copy_array (o, 0, mono_array_addr_with_size (array, 0, 0), mono_array_length (array));
else
- memcpy (&o->vector, &array->vector, size);
+ mono_gc_memmove (&o->vector, &array->vector, size);
} else {
mono_array_memcpy_refs (o, 0, array, 0, mono_array_length (array));
}
#else
- memcpy (&o->vector, &array->vector, size);
+ mono_gc_memmove (&o->vector, &array->vector, size);
#endif
return o;
#endif
gboolean
-mono_array_calc_byte_len (MonoClass *class, mono_array_size_t len, mono_array_size_t *res)
+mono_array_calc_byte_len (MonoClass *class, uintptr_t len, uintptr_t *res)
{
- mono_array_size_t byte_len;
+ uintptr_t byte_len;
byte_len = mono_array_element_size (class);
if (CHECK_MUL_OVERFLOW_UN (byte_len, len))
* lower bounds and type.
*/
MonoArray*
-mono_array_new_full (MonoDomain *domain, MonoClass *array_class, mono_array_size_t *lengths, mono_array_size_t *lower_bounds)
+mono_array_new_full (MonoDomain *domain, MonoClass *array_class, uintptr_t *lengths, intptr_t *lower_bounds)
{
- mono_array_size_t byte_len, len, bounds_size;
+ uintptr_t byte_len, len, bounds_size;
MonoObject *o;
MonoArray *array;
MonoArrayBounds *bounds;
* This routine creates a new szarray with @n elements of type @eclass.
*/
MonoArray *
-mono_array_new (MonoDomain *domain, MonoClass *eclass, mono_array_size_t n)
+mono_array_new (MonoDomain *domain, MonoClass *eclass, uintptr_t n)
{
MonoClass *ac;
* can be sure about the domain it operates in.
*/
MonoArray *
-mono_array_new_specific (MonoVTable *vtable, mono_array_size_t n)
+mono_array_new_specific (MonoVTable *vtable, uintptr_t n)
{
MonoObject *o;
MonoArray *ao;
- guint32 byte_len;
+ uintptr_t byte_len;
MONO_ARCH_SAVE_REGS;
mono_gc_wbarrier_value_copy ((char *)res + sizeof (MonoObject), value, 1, class);
#else
#if NO_UNALIGNED_ACCESS
- memcpy ((char *)res + sizeof (MonoObject), value, size);
+ mono_gc_memmove ((char *)res + sizeof (MonoObject), value, size);
#else
switch (size) {
case 1:
*(guint64 *)((guint8 *) res + sizeof (MonoObject)) = *(guint64 *) value;
break;
default:
- memcpy ((char *)res + sizeof (MonoObject), value, size);
+ mono_gc_memmove ((char *)res + sizeof (MonoObject), value, size);
}
#endif
#endif
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;
}
MonoString *news;
size = sizeof (MonoString) + 2 * (mono_string_length (str) + 1);
news = mono_gc_alloc_pinned_obj (((MonoObject*)str)->vtable, size);
- memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
- news->length = mono_string_length (str);
+ if (news) {
+ memcpy (mono_string_chars (news), mono_string_chars (str), mono_string_length (str) * 2);
+ news->length = mono_string_length (str);
+ }
return news;
}
}
if (insert) {
str = mono_string_get_pinned (str);
- mono_g_hash_table_insert (ldstr_table, str, str);
+ if (str)
+ mono_g_hash_table_insert (ldstr_table, str, str);
ldstr_unlock ();
return str;
} else {
}
o = mono_string_get_pinned (o);
- mono_g_hash_table_insert (domain->ldstr_table, o, o);
+ if (o)
+ mono_g_hash_table_insert (domain->ldstr_table, o, o);
ldstr_unlock ();
return o;
* mono_string_to_utf8:
* @s: a System.String
*
- * Return the UTF8 representation for @s.
- * the resulting buffer nedds to be freed with g_free().
+ * Returns the UTF8 representation for @s.
+ * The resulting buffer needs to be freed with mono_free().
*
* @deprecated Use mono_string_to_utf8_checked to avoid having an exception arbritraly raised.
*/
return result;
}
+/**
+ * mono_string_to_utf8_checked:
+ * @s: a System.String
+ * @error: a MonoError.
+ *
+ * Converts a MonoString to its UTF8 representation. May fail; check
+ * @error to determine whether the conversion was successful.
+ * The resulting buffer should be freed with mono_free().
+ */
char *
mono_string_to_utf8_checked (MonoString *s, MonoError *error)
{
return as;
}
+/**
+ * mono_string_to_utf8_ignore:
+ * @s: a MonoString
+ *
+ * Converts a MonoString to its UTF8 representation. Will ignore
+ * invalid surrogate pairs.
+ * The resulting buffer should be freed with mono_free().
+ *
+ */
+char *
+mono_string_to_utf8_ignore (MonoString *s)
+{
+ long written = 0;
+ char *as;
+
+ if (s == NULL)
+ return NULL;
+
+ if (!s->length)
+ return g_strdup ("");
+
+ as = g_utf16_to_utf8 (mono_string_chars (s), s->length, NULL, &written, NULL);
+
+ /* g_utf16_to_utf8 may not be able to complete the convertion (e.g. NULL values were found, #335488) */
+ if (s->length > written) {
+ /* allocate the total length and copy the part of the string that has been converted */
+ char *as2 = g_malloc0 (s->length);
+ memcpy (as2, as, written);
+ g_free (as);
+ as = as2;
+ }
+
+ return as;
+}
+
+/**
+ * mono_string_to_utf8_image_ignore:
+ * @s: a System.String
+ *
+ * Same as mono_string_to_utf8_ignore, but allocate the string from the image mempool.
+ */
+char *
+mono_string_to_utf8_image_ignore (MonoImage *image, MonoString *s)
+{
+ return mono_string_to_utf8_internal (NULL, image, s, TRUE, NULL);
+}
+
+/**
+ * mono_string_to_utf8_mp_ignore:
+ * @s: a System.String
+ *
+ * Same as mono_string_to_utf8_ignore, but allocate the string from a mempool.
+ */
+char *
+mono_string_to_utf8_mp_ignore (MonoMemPool *mp, MonoString *s)
+{
+ return mono_string_to_utf8_internal (mp, NULL, s, TRUE, NULL);
+}
+
+
/**
* mono_string_to_utf16:
* @s: a MonoString
* This is a temporary helper until our string implementation
* is reworked to always include the null terminating char.
*/
-gunichar2 *
+mono_unichar2*
mono_string_to_utf16 (MonoString *s)
{
char *as;
static char *
-mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, MonoError *error)
+mono_string_to_utf8_internal (MonoMemPool *mp, MonoImage *image, MonoString *s, gboolean ignore_error, MonoError *error)
{
char *r;
char *mp_s;
int len;
- r = mono_string_to_utf8_checked (s, error);
- if (!mono_error_ok (error))
- return NULL;
+ if (ignore_error) {
+ r = mono_string_to_utf8_ignore (s);
+ } else {
+ r = mono_string_to_utf8_checked (s, error);
+ if (!mono_error_ok (error))
+ return NULL;
+ }
if (!mp && !image)
return r;
char *
mono_string_to_utf8_image (MonoImage *image, MonoString *s, MonoError *error)
{
- return mono_string_to_utf8_internal (NULL, image, s, error);
+ return mono_string_to_utf8_internal (NULL, image, s, FALSE, error);
}
/**
char *
mono_string_to_utf8_mp (MonoMemPool *mp, MonoString *s, MonoError *error)
{
- return mono_string_to_utf8_internal (mp, NULL, s, error);
+ return mono_string_to_utf8_internal (mp, NULL, s, FALSE, error);
}
-static void
-default_ex_handler (MonoException *ex)
-{
- MonoObject *o = (MonoObject*)ex;
- g_error ("Exception %s.%s raised in C code", o->vtable->klass->name_space, o->vtable->klass->name);
- exit (1);
-}
-static MonoExceptionFunc ex_handler = default_ex_handler;
+static MonoRuntimeExceptionHandlingCallbacks eh_callbacks;
-/**
- * mono_install_handler:
- * @func: exception handler
- *
- * This is an internal JIT routine used to install the handler for exceptions
- * being throwh.
- */
void
-mono_install_handler (MonoExceptionFunc func)
+mono_install_eh_callbacks (MonoRuntimeExceptionHandlingCallbacks *cbs)
{
- ex_handler = func? func: default_ex_handler;
+ eh_callbacks = *cbs;
+}
+
+MonoRuntimeExceptionHandlingCallbacks *
+mono_get_eh_callbacks (void)
+{
+ return &eh_callbacks;
}
/**
MONO_OBJECT_SETREF (thread, abort_exc, ex);
}
- ex_handler (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);
}
/**
return ret;
}
+/**
+ * mono_object_to_string:
+ * @obj: The object
+ * @exc: Any exception thrown by ToString (). May be NULL.
+ *
+ * Returns: the result of calling ToString () on an object.
+ */
+MonoString *
+mono_object_to_string (MonoObject *obj, MonoObject **exc)
+{
+ static MonoMethod *to_string = NULL;
+ MonoMethod *method;
+
+ g_assert (obj);
+
+ if (!to_string)
+ to_string = mono_class_get_method_from_name_flags (mono_get_object_class (), "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
+
+ method = mono_object_get_virtual_method (obj, to_string);
+
+ return (MonoString *) mono_runtime_invoke (method, obj, NULL, exc);
+}
+
/**
* mono_print_unhandled_exception:
* @exc: The exception
void
mono_print_unhandled_exception (MonoObject *exc)
{
- MonoError error;
- char *message = (char *) "";
- MonoString *str;
- MonoMethod *method;
- MonoClass *klass;
+ MonoString * str;
+ char *message = (char*)"";
gboolean free_message = FALSE;
+ MonoError error;
- if (mono_object_isinst (exc, mono_defaults.exception_class)) {
- klass = exc->vtable->klass;
- method = NULL;
- while (klass && method == NULL) {
- method = mono_class_get_method_from_name_flags (klass, "ToString", 0, METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_PUBLIC);
- if (method == NULL)
- klass = klass->parent;
- }
-
- g_assert (method);
-
- str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
+ if (exc == (MonoObject*)mono_object_domain (exc)->out_of_memory_ex) {
+ message = g_strdup ("OutOfMemoryException");
+ } 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 *)"";
+ message = (char *) "";
} else {
free_message = TRUE;
}
}
- }
+ }
/*
* g_printerr ("\nUnhandled Exception: %s.%s: %s\n", exc->vtable->klass->name_space,
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);
}
if (class->has_references)
mono_gc_wbarrier_value_copy (*((gpointer *)params [i]), arg + sizeof (MonoObject), 1, class);
else
- memcpy (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
+ mono_gc_memmove (*((gpointer *)params [i]), arg + sizeof (MonoObject), size);
} else {
size = mono_class_value_size (mono_class_from_mono_type (pt), NULL);
- memset (*((gpointer *)params [i]), 0, size);
+ mono_gc_bzero (*((gpointer *)params [i]), size);
}
}
return callbacks.get_addr_from_ftnptr (descr);
}
-#if 0
/**
* mono_string_chars:
* @s: a MonoString
* Returns a pointer to the UCS16 characters stored in the MonoString
*/
gunichar2 *
-mono_string_chars(MonoString *s)
+mono_string_chars (MonoString *s)
{
- /* This method is here only for documentation extraction, this is a macro */
+ return s->chars;
}
/**
int
mono_string_length (MonoString *s)
{
- /* This method is here only for documentation extraction, this is a macro */
+ return s->length;
+}
+
+/**
+ * mono_array_length:
+ * @array: a MonoArray*
+ *
+ * Returns the total number of elements in the array. This works for
+ * both vectors and multidimensional arrays.
+ */
+uintptr_t
+mono_array_length (MonoArray *array)
+{
+ return array->max_length;
+}
+
+/**
+ * mono_array_addr_with_size:
+ * @array: a MonoArray*
+ * @size: size of the array elements
+ * @idx: index into the array
+ *
+ * Returns the address of the @idx element in the array.
+ */
+char*
+mono_array_addr_with_size (MonoArray *array, int size, uintptr_t idx)
+{
+ return ((char*)(array)->vector) + size * idx;
}
-#endif