#endif
#include <stdlib.h>
#include <stdio.h>
-#include <signal.h>
#include <string.h>
#include <mono/metadata/mono-endian.h>
#include <mono/metadata/tabledefs.h>
#define mono_type_initialization_unlock() mono_mutex_unlock (&type_initialization_section)
static mono_mutex_t type_initialization_section;
+
+static void
+mono_type_init_lock (TypeInitializationLock *lock)
+{
+ MONO_TRY_BLOCKING
+ mono_mutex_lock (&lock->initialization_section);
+ MONO_FINISH_TRY_BLOCKING
+}
+
+static void
+mono_type_init_unlock (TypeInitializationLock *lock)
+{
+ mono_mutex_unlock (&lock->initialization_section);
+}
+
/* from vtable to lock */
static GHashTable *type_initialization_hash;
MonoClass *klass;
gchar *full_name;
- MONO_ARCH_SAVE_REGS;
-
if (vtable->initialized)
return NULL;
lock->waiting_count = 1;
lock->done = FALSE;
/* grab the vtable lock while this thread still owns type_initialization_section */
- mono_mutex_lock (&lock->initialization_section);
+ mono_type_init_lock (lock);
g_hash_table_insert (type_initialization_hash, vtable, lock);
do_initialization = 1;
} else {
if (last_domain)
mono_domain_set (last_domain, TRUE);
lock->done = TRUE;
- mono_mutex_unlock (&lock->initialization_section);
+ mono_type_init_unlock (lock);
} else {
/* this just blocks until the initializing thread is done */
- mono_mutex_lock (&lock->initialization_section);
- mono_mutex_unlock (&lock->initialization_section);
+ mono_type_init_lock (lock);
+ mono_type_init_unlock (lock);
}
mono_type_initialization_lock ();
* and get_type_init_exception_for_class () needs to be aware of this.
*/
vtable->init_failed = 1;
- mono_mutex_unlock (&lock->initialization_section);
+ mono_type_init_unlock (lock);
--lock->waiting_count;
if (lock->waiting_count == 0) {
mono_mutex_destroy (&lock->initialization_section);
static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
static MonoJumpTrampoline arch_create_jump_trampoline = default_jump_trampoline;
static MonoDelegateTrampoline arch_create_delegate_trampoline = default_delegate_trampoline;
-static MonoImtThunkBuilder imt_thunk_builder = NULL;
-#define ARCH_USE_IMT (imt_thunk_builder != NULL)
+static MonoImtThunkBuilder imt_thunk_builder;
#if (MONO_IMT_SIZE > 32)
#error "MONO_IMT_SIZE cannot be larger than 32"
#endif
class->gc_descr = (gpointer)mono_gc_make_descr_for_string (bitmap, 2);
} else if (class->rank) {
mono_class_compute_gc_descriptor (class->element_class);
- if (!class->element_class->valuetype) {
+ if (MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg)) {
gsize abm = 1;
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,
* 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], callbacks.get_imt_trampoline ? callbacks.get_imt_trampoline (i) : NULL);
+ imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], callbacks.get_imt_trampoline (i));
} else {
imt [i] = initialize_imt_slot (vt, domain, imt_builder [i], NULL);
}
return NULL;
}
+static gpointer*
+alloc_vtable (MonoDomain *domain, size_t vtable_size, size_t imt_table_bytes)
+{
+ size_t alloc_offset;
+
+ /*
+ * We want the pointer to the MonoVTable aligned to 8 bytes because SGen uses three
+ * address bits. The IMT has an odd number of entries, however, so on 32 bits the
+ * alignment will be off. In that case we allocate 4 more bytes and skip over them.
+ */
+ if (sizeof (gpointer) == 4 && (imt_table_bytes & 7)) {
+ g_assert ((imt_table_bytes & 7) == 4);
+ vtable_size += 4;
+ alloc_offset = 4;
+ } else {
+ alloc_offset = 0;
+ }
+
+ return (gpointer*) ((char*)mono_domain_alloc0 (domain, vtable_size) + alloc_offset);
+}
+
static MonoVTable *
mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *class, gboolean raise_on_error)
{
MonoClassField *field;
char *t;
int i, vtable_slots;
- int imt_table_bytes = 0;
+ size_t imt_table_bytes;
int gc_bits;
guint32 vtable_size, class_size;
- guint32 cindex;
gpointer iter;
gpointer *interface_offsets;
if (class_size)
vtable_slots++;
- if (ARCH_USE_IMT) {
- 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);
- mono_stats.imt_number_of_tables++;
- mono_stats.imt_tables_size += (sizeof (gpointer) * MONO_IMT_SIZE);
- }
+ if (class->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;
} else {
- vtable_size = sizeof (gpointer) * (class->max_interface_id + 1) +
- MONO_SIZEOF_VTABLE + vtable_slots * sizeof (gpointer);
+ 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;
- interface_offsets = mono_domain_alloc0 (domain, vtable_size);
- if (ARCH_USE_IMT)
- vt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes);
- else
- vt = (MonoVTable*) (interface_offsets + class->max_interface_id + 1);
+ interface_offsets = alloc_vtable (domain, vtable_size, imt_table_bytes);
+ vt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes);
+ g_assert (!((gsize)vt & 7));
+
vt->klass = class;
vt->rank = class->rank;
vt->domain = domain;
mono_stats.class_static_data_size += class_size;
}
- cindex = -1;
iter = NULL;
while ((field = mono_class_get_fields (class, &iter))) {
if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
//printf ("Initializing VT for class %s (interface_offsets_count = %d)\n",
// class->name, class->interface_offsets_count);
-
- 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;
- int slot = class->interface_offsets_packed [i];
- interface_offsets [class->max_interface_id - interface_id] = &(vt->vtable [slot]);
- }
- }
/* Initialize vtable */
if (callbacks.get_vtable_trampoline) {
}
}
- if (ARCH_USE_IMT && imt_table_bytes) {
+ if (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);
- }
}
/*
gpointer *interface_offsets;
uint8_t *bitmap;
int bsize;
+ size_t imt_table_bytes;
#ifdef COMPRESSED_INTERFACE_BITMAP
int bcsize;
if (iclass->max_interface_id > max_interface_id) max_interface_id = iclass->max_interface_id;
}
- if (ARCH_USE_IMT) {
- mono_stats.imt_number_of_tables++;
- mono_stats.imt_tables_size += (sizeof (gpointer) * MONO_IMT_SIZE);
- vtsize = sizeof (gpointer) * (MONO_IMT_SIZE) +
- MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
- } else {
- vtsize = sizeof (gpointer) * (max_interface_id + 1) +
- MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
- }
+ imt_table_bytes = sizeof (gpointer) * MONO_IMT_SIZE;
+ mono_stats.imt_number_of_tables++;
+ mono_stats.imt_tables_size += imt_table_bytes;
+
+ vtsize = imt_table_bytes + MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer);
mono_stats.class_vtable_size += vtsize + extra_interface_vtsize;
- interface_offsets = mono_domain_alloc0 (domain, vtsize + extra_interface_vtsize);
- if (ARCH_USE_IMT)
- pvt = (MonoVTable*) (interface_offsets + MONO_IMT_SIZE);
- else
- pvt = (MonoVTable*) (interface_offsets + max_interface_id + 1);
+ interface_offsets = alloc_vtable (domain, vtsize + extra_interface_vtsize, imt_table_bytes);
+ pvt = (MonoVTable*) ((char*)interface_offsets + imt_table_bytes);
+ g_assert (!((gsize)pvt & 7));
+
memcpy (pvt, vt, MONO_SIZEOF_VTABLE + class->vtable_size * sizeof (gpointer));
pvt->klass = mono_defaults.transparent_proxy_class;
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;
- int slot = class->interface_offsets_packed [i];
- interface_offsets [class->max_interface_id - interface_id] = &(pvt->vtable [slot]);
- }
- }
for (i = 0; i < class->interface_offsets_count; ++i) {
int interface_id = class->interfaces_packed [i]->interface_id;
bitmap [interface_id >> 3] |= (1 << (interface_id & 7));
for (list_item = extra_interfaces; list_item != NULL; list_item=list_item->next) {
interf = list_item->data;
- if (! ARCH_USE_IMT) {
- interface_offsets [max_interface_id - interf->interface_id] = &pvt->vtable [slot];
- }
bitmap [interf->interface_id >> 3] |= (1 << (interf->interface_id & 7));
iter = NULL;
slot += mono_class_num_methods (interf);
}
- if (! ARCH_USE_IMT) {
- g_slist_free (extra_interfaces);
- }
}
- if (ARCH_USE_IMT) {
- /* Now that the vtable is full, we can actually fill up the IMT */
- build_imt (class, pvt, domain, interface_offsets, extra_interfaces);
- if (extra_interfaces) {
- g_slist_free (extra_interfaces);
- }
+ /* Now that the vtable is full, we can actually fill up the IMT */
+ build_imt (class, pvt, domain, interface_offsets, extra_interfaces);
+ if (extra_interfaces) {
+ g_slist_free (extra_interfaces);
}
#ifdef COMPRESSED_INTERFACE_BITMAP
#endif
{
if (method->is_inflated) {
+ MonoError error;
/* Have to inflate the result */
- res = mono_class_inflate_generic_method (res, &((MonoMethodInflated*)method)->context);
+ res = mono_class_inflate_generic_method_checked (res, &((MonoMethodInflated*)method)->context, &error);
+ g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
}
}
return mono_compile_method (method);
}
-static void
-set_value (MonoType *type, void *dest, void *value, int deref_pointer)
+void
+mono_copy_value (MonoType *type, void *dest, void *value, int deref_pointer)
{
int t;
if (type->byref) {
g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
dest = (char*)obj + field->offset;
- set_value (field->type, dest, value, FALSE);
+ mono_copy_value (field->type, dest, value, FALSE);
}
/**
} else {
dest = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
}
- set_value (field->type, dest, value, FALSE);
+ mono_copy_value (field->type, dest, value, FALSE);
}
/**
g_return_if_fail (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC));
src = (char*)obj + field->offset;
- set_value (field->type, value, src, TRUE);
+ mono_copy_value (field->type, value, src, TRUE);
}
/**
}
/* MONO_TYPE_PTR is passed by value to runtime_invoke () */
- args [0] = *ptr;
+ args [0] = ptr ? *ptr : NULL;
args [1] = mono_type_get_object (mono_domain_get (), type);
return mono_runtime_invoke (m, NULL, args, NULL);
} else {
src = (char*)mono_vtable_get_static_field_data (vt) + field->offset;
}
- set_value (field->type, value, src, TRUE);
+ mono_copy_value (field->type, value, src, TRUE);
}
/**
mono_object_allocate (size_t size, MonoVTable *vtable)
{
MonoObject *o;
- mono_stats.new_object_count++;
ALLOC_OBJECT (o, vtable, size);
return o;
}
+#ifndef HAVE_SGEN_GC
/**
* mono_object_allocate_ptrfree:
* @size: number of bytes to allocate
mono_object_allocate_ptrfree (size_t size, MonoVTable *vtable)
{
MonoObject *o;
- mono_stats.new_object_count++;
ALLOC_PTRFREE (o, vtable, size);
return o;
}
+#endif
static inline void *
mono_object_allocate_spec (size_t size, MonoVTable *vtable)
{
void *o;
ALLOC_TYPED (o, size, vtable);
- mono_stats.new_object_count++;
return o;
}
{
MonoVTable *vtable;
- MONO_ARCH_SAVE_REGS;
vtable = mono_class_vtable (domain, klass);
if (!vtable)
return NULL;
{
MonoVTable *vtable;
- MONO_ARCH_SAVE_REGS;
vtable = mono_class_vtable (domain, klass);
if (!vtable)
return NULL;
{
MonoObject *o;
- MONO_ARCH_SAVE_REGS;
-
/* check for is_com_object for COM Interop */
if (mono_vtable_is_remote (vtable) || mono_class_is_com_object (vtable->klass))
{
o = mono_object_allocate (size, obj->vtable);
- if (obj->vtable->klass->has_references) {
- mono_gc_wbarrier_object_copy (o, obj);
- } else {
- int size = obj->vtable->klass->instance_size;
- /* do not copy the sync state */
- mono_gc_memmove_atomic ((char*)o + sizeof (MonoObject), (char*)obj + sizeof (MonoObject), size - sizeof (MonoObject));
- }
+ /* If the object doesn't contain references this will do a simple memmove. */
+ mono_gc_wbarrier_object_copy (o, obj);
+
if (G_UNLIKELY (profile_allocs))
mono_profiler_allocation (o, obj->vtable->klass);
uintptr_t size;
MonoClass *klass = src->obj.vtable->klass;
- MONO_ARCH_SAVE_REGS;
-
g_assert (klass == dest->obj.vtable->klass);
size = mono_array_length (src);
uintptr_t *sizes;
MonoClass *klass = array->obj.vtable->klass;
- MONO_ARCH_SAVE_REGS;
-
if (array->bounds == NULL) {
size = mono_array_length (array);
o = mono_array_new_full (domain, klass, &size, NULL);
else
o = mono_gc_alloc_vector (vtable, byte_len, len);
array = (MonoArray*)o;
- mono_stats.new_object_count++;
bounds = array->bounds;
#endif
{
MonoClass *ac;
- MONO_ARCH_SAVE_REGS;
-
ac = mono_array_class_get (eclass, 1);
g_assert (ac);
MonoArray *ao;
uintptr_t byte_len;
- MONO_ARCH_SAVE_REGS;
-
if (G_UNLIKELY (n > MONO_ARRAY_MAX_INDEX)) {
arith_overflow ();
return NULL;
#else
o = mono_gc_alloc_vector (vtable, byte_len, n);
ao = (MonoArray*)o;
- mono_stats.new_object_count++;
#endif
if (G_UNLIKELY (profile_allocs))
size_t size;
/* check for overflow */
- if (len < 0 || len > ((SIZE_MAX - offsetof (MonoString, chars) - 2) / 2))
+ if (len < 0 || len > ((SIZE_MAX - G_STRUCT_OFFSET (MonoString, chars) - 8) / 2))
mono_gc_out_of_memory (-1);
- size = (offsetof (MonoString, chars) + ((len + 1) * 2));
+ size = (G_STRUCT_OFFSET (MonoString, chars) + (((size_t)len + 1) * 2));
g_assert (size > 0);
vtable = mono_class_vtable (domain, mono_defaults.string_class);
{
MonoDomain *domain = mono_domain_get ();
- MONO_ARCH_SAVE_REGS;
-
if (text)
return mono_string_new (domain, text);
mono_string_is_interned_lookup (MonoString *str, int insert)
{
MonoGHashTable *ldstr_table;
- MonoString *res;
+ MonoString *s, *res;
MonoDomain *domain;
domain = ((MonoObject *)str)->vtable->domain;
ldstr_table = domain->ldstr_table;
ldstr_lock ();
- if ((res = mono_g_hash_table_lookup (ldstr_table, str))) {
+ res = mono_g_hash_table_lookup (ldstr_table, str);
+ if (res) {
ldstr_unlock ();
return res;
}
if (insert) {
- str = mono_string_get_pinned (str);
- if (str)
- mono_g_hash_table_insert (ldstr_table, str, str);
+ /* Allocate outside the lock */
ldstr_unlock ();
- return str;
+ s = mono_string_get_pinned (str);
+ if (s) {
+ ldstr_lock ();
+ res = mono_g_hash_table_lookup (ldstr_table, str);
+ if (res) {
+ ldstr_unlock ();
+ return res;
+ }
+ mono_g_hash_table_insert (ldstr_table, s, s);
+ ldstr_unlock ();
+ }
+ return s;
} else {
LDStrInfo ldstr_info;
ldstr_info.orig_domain = domain;
MonoString*
mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
{
- MONO_ARCH_SAVE_REGS;
-
if (image->dynamic) {
MonoString *str = mono_lookup_dynamic_token (image, MONO_TOKEN_STRING | idx, NULL);
return str;
}
#endif
ldstr_lock ();
- if ((interned = mono_g_hash_table_lookup (domain->ldstr_table, o))) {
- ldstr_unlock ();
- /* o will get garbage collected */
- return interned;
- }
+ interned = mono_g_hash_table_lookup (domain->ldstr_table, o);
+ ldstr_unlock ();
+ if (interned)
+ return interned; /* o will get garbage collected */
o = mono_string_get_pinned (o);
- if (o)
- mono_g_hash_table_insert (domain->ldstr_table, o, o);
- ldstr_unlock ();
+ if (o) {
+ ldstr_lock ();
+ interned = mono_g_hash_table_lookup (domain->ldstr_table, o);
+ if (!interned) {
+ mono_g_hash_table_insert (domain->ldstr_table, o, o);
+ interned = o;
+ }
+ ldstr_unlock ();
+ }
- return o;
+ return interned;
}
/**
return res;
}
+MonoObject *
+mono_async_result_invoke (MonoAsyncResult *ares, MonoObject **exc)
+{
+ MonoAsyncCall *ac;
+ MonoObject *res;
+ MonoInternalThread *thread;
+
+ g_assert (ares);
+ g_assert (ares->async_delegate);
+
+ thread = mono_thread_internal_current ();
+
+ if (!ares->execution_context) {
+ ares->original_context = NULL;
+ } else {
+ /* use captured ExecutionContext (if available) */
+ MONO_OBJECT_SETREF (ares, original_context, mono_thread_get_execution_context ());
+ mono_thread_set_execution_context (ares->execution_context);
+ }
+
+ ac = (MonoAsyncCall*) ares->object_data;
+ if (!ac) {
+ thread->async_invoke_method = ((MonoDelegate*) ares->async_delegate)->method;
+ res = mono_runtime_delegate_invoke (ares->async_delegate, (void**) &ares->async_state, exc);
+ thread->async_invoke_method = NULL;
+ } else {
+ MonoArray *out_args = NULL;
+ gpointer wait_event = NULL;
+
+ ac->msg->exc = NULL;
+ res = mono_message_invoke (ares->async_delegate, ac->msg, exc, &out_args);
+ MONO_OBJECT_SETREF (ac->msg, exc, *exc);
+ MONO_OBJECT_SETREF (ac, res, res);
+ MONO_OBJECT_SETREF (ac, out_args, out_args);
+
+ mono_monitor_enter ((MonoObject*) ares);
+ ares->completed = 1;
+ if (ares->handle)
+ wait_event = mono_wait_handle_get_handle ((MonoWaitHandle*) ares->handle);
+ mono_monitor_exit ((MonoObject*) ares);
+
+ if (wait_event != NULL)
+ SetEvent (wait_event);
+
+ if (!ac->cb_method) {
+ *exc = NULL;
+ } else {
+ thread->async_invoke_method = ac->cb_method;
+ mono_runtime_invoke (ac->cb_method, ac->cb_target, (gpointer*) &ares, exc);
+ thread->async_invoke_method = NULL;
+ }
+ }
+
+ /* restore original thread execution context if flow isn't suppressed, i.e. non null */
+ if (ares->original_context) {
+ mono_thread_set_execution_context (ares->original_context);
+ ares->original_context = NULL;
+ }
+
+ return res;
+}
+
+MonoObject *
+ves_icall_System_Runtime_Remoting_Messaging_AsyncResult_Invoke (MonoAsyncResult *this)
+{
+ MonoObject *exc = NULL;
+ MonoObject *res = mono_async_result_invoke (this, &exc);
+ if (exc)
+ mono_raise_exception ((MonoException*) exc);
+ return res;
+}
+
void
mono_message_init (MonoDomain *domain,
MonoMethodMessage *this,
mono_delegate_ctor_with_method (MonoObject *this, MonoObject *target, gpointer addr, MonoMethod *method)
{
MonoDelegate *delegate = (MonoDelegate *)this;
- MonoClass *class;
g_assert (this);
g_assert (addr);
if (method)
delegate->method = method;
- class = this->vtable->klass;
mono_stats.delegate_creations++;
#ifndef DISABLE_REMOTING
MonoDomain *domain = mono_domain_get ();
MonoMethodSignature *sig = mono_method_signature (method);
MonoMethodMessage *msg;
- int i, count, type;
+ int i, count;
msg = (MonoMethodMessage *)mono_object_new (domain, mono_defaults.mono_method_message_class);
else
vpos = params [i];
- type = sig->params [i]->type;
class = mono_class_from_mono_type (sig->params [i]);
if (class->valuetype)