#include <mono/utils/mono-mmap.h>
#include <mono/utils/mono-io-portability.h>
#include <mono/utils/mono-digest.h>
+#include <mono/utils/bsearch.h>
+#include <mono/utils/mono-mutex.h>
#if defined (HOST_WIN32)
#include <windows.h>
ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
{
int sz = mono_array_element_size (mono_object_class (arr));
- mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
+ mono_gc_bzero (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
}
ICALL_EXPORT gboolean
int element_size;
void * dest_addr;
void * source_addr;
+ MonoVTable *src_vtable;
+ MonoVTable *dest_vtable;
MonoClass *src_class;
MonoClass *dest_class;
- MONO_ARCH_SAVE_REGS;
+ src_vtable = source->obj.vtable;
+ dest_vtable = dest->obj.vtable;
- if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
+ if (src_vtable->rank != dest_vtable->rank)
return FALSE;
if (source->bounds || dest->bounds)
return FALSE;
/* there's no integer overflow since mono_array_length returns an unsigned integer */
- if ((dest_idx + length > mono_array_length (dest)) ||
- (source_idx + length > mono_array_length (source)))
+ if ((dest_idx + length > mono_array_length_fast (dest)) ||
+ (source_idx + length > mono_array_length_fast (source)))
return FALSE;
- src_class = source->obj.vtable->klass->element_class;
- dest_class = dest->obj.vtable->klass->element_class;
+ src_class = src_vtable->klass->element_class;
+ dest_class = dest_vtable->klass->element_class;
/*
* Handle common cases.
*/
- /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
- if (src_class == mono_defaults.object_class && dest_class->valuetype) {
- // FIXME: This is racy
+ /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
+ We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
+ */
+ if (src_class == mono_defaults.object_class && dest_class->valuetype)
return FALSE;
- /*
- int i;
- int has_refs = dest_class->has_references;
- for (i = source_idx; i < source_idx + length; ++i) {
- MonoObject *elem = mono_array_get (source, MonoObject*, i);
- if (elem && !mono_object_isinst (elem, dest_class))
- return FALSE;
- }
-
- element_size = mono_array_element_size (dest->obj.vtable->klass);
- memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
- for (i = 0; i < length; ++i) {
- MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
- void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
- if (!elem)
- continue;
- if (has_refs)
- mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
- else
- memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
- }
- return TRUE;
- */
- }
/* Check if we're copying a char[] <==> (u)short[] */
if (src_class != dest_class) {
if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
return FALSE;
- if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
- ;
- /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
- else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
- // FIXME: This is racy
- return FALSE;
- /*
- int i;
- for (i = source_idx; i < source_idx + length; ++i) {
- MonoObject *elem = mono_array_get (source, MonoObject*, i);
- if (elem && !mono_object_isinst (elem, dest_class))
- return FALSE;
- }
- */
- } else
+ /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
+ if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
return FALSE;
}
if (dest_class->valuetype) {
element_size = mono_array_element_size (source->obj.vtable->klass);
- source_addr = mono_array_addr_with_size (source, element_size, source_idx);
+ source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
if (dest_class->has_references) {
mono_value_copy_array (dest, dest_idx, source_addr, length);
} else {
- dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
+ dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
mono_gc_memmove (dest_addr, source_addr, element_size * length);
}
} else {
- mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
+ mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
}
return TRUE;
}
#else
memcpy (mono_array_addr (array, char, 0), field_data, size);
-#ifdef ARM_FPU_FPA
- if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
- gint i;
- double tmp;
- double *data = (double*)mono_array_addr (array, double, 0);
-
- for (i = 0; i < size; i++, data++) {
- readr8 (data, &tmp);
- *data = tmp;
- }
- }
-#endif
#endif
}
int i;
mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
for (i = 0; i < count; ++i)
- mono_array_setref (*fields, i, values [i]);
+ mono_array_setref_fast (*fields, i, values [i]);
return FALSE;
} else {
return TRUE;
mono_class_init_or_throw (klass);
mono_class_init_or_throw (klassc);
} else if (!klass->supertypes || !klassc->supertypes) {
- mono_loader_lock ();
mono_class_setup_supertypes (klass);
mono_class_setup_supertypes (klassc);
- mono_loader_unlock ();
}
if (type->type->byref)
* FIXME: Why is this stuff needed at all ? Why can't the code below work for
* the dynamic case as well ?
*/
- mono_loader_lock ();
+ mono_image_lock ((MonoImage*)image);
res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
- mono_loader_unlock ();
+ mono_image_unlock ((MonoImage*)image);
if (res)
return res;
*/
MonoMethod *m = method->method;
MonoMethodSignature *sig = mono_method_signature (m);
+ MonoImage *image;
int pcount;
void *obj = this;
return NULL;
}
- if (m->klass->image->assembly->ref_only) {
+ image = m->klass->image;
+ if (image->assembly->ref_only) {
mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
return NULL;
}
+
+ if (image->dynamic && !((MonoDynamicImage*)image)->run) {
+ mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
+ return NULL;
+ }
if (m->klass->rank && !strcmp (m->name, ".ctor")) {
int i;
struct tm start, tt;
time_t t;
- long int gmtoff;
- int is_daylight = 0, day;
+ long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
+ int day, transitioned;
char tzone [64];
+ gmtoff_st = gmtoff_ds = transitioned = 0;
+
MONO_ARCH_SAVE_REGS;
MONO_CHECK_ARG_NULL (data);
gmtoff = gmt_offset (&start, t);
/* For each day of the year, calculate the tm_gmtoff. */
- for (day = 0; day < 365; day++) {
+ for (day = 0; day < 365 && transitioned < 2; day++) {
t += 3600*24;
tt = *localtime (&t);
+ gmtoff_after = gmt_offset(&tt, t);
+
/* Daylight saving starts or ends here. */
- if (gmt_offset (&tt, t) != gmtoff) {
+ if (gmtoff_after != gmtoff) {
struct tm tt1;
time_t t1;
strftime (tzone, sizeof (tzone), "%Z", &tt);
/* Write data, if we're already in daylight saving, we're done. */
- if (is_daylight) {
- mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
- mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
- return 1;
+ if (tt.tm_isdst) {
+ mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
+ mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
+ if (gmtoff_ds == 0) {
+ gmtoff_st = gmtoff;
+ gmtoff_ds = gmtoff_after;
+ }
+ transitioned++;
} else {
- struct tm end;
time_t te;
+ te = mktime (&tt);
- memset (&end, 0, sizeof (end));
- end.tm_year = year-1900 + 1;
- end.tm_mday = 1;
-
- te = mktime (&end);
-
- mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
- mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
- mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
- is_daylight = 1;
+ mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
+ if (gmtoff_ds == 0) {
+ gmtoff_st = gmtoff_after;
+ gmtoff_ds = gmtoff;
+ }
+ transitioned++;
}
/* This is only set once when we enter daylight saving. */
- mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
- mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
-
+ if (tt1.tm_isdst) {
+ mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
+ mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
+ }
gmtoff = gmt_offset (&tt, t);
}
}
- if (!is_daylight) {
+ if (transitioned < 2) {
strftime (tzone, sizeof (tzone), "%Z", &tt);
mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
{
MONO_ARCH_SAVE_REGS;
+ mono_environment_exitcode_set (result);
+
/* FIXME: There are some cleanup hangs that should be worked out, but
* if the program is going to exit, everything will be cleaned up when
* NaCl exits anyway.
*/
#ifndef __native_client__
- mono_runtime_shutdown ();
-
- /* This will kill the tp threads which cannot be suspended */
- mono_thread_pool_cleanup ();
+ if (!mono_runtime_try_shutdown ())
+ mono_thread_exit ();
/* Suspend all managed threads since the runtime is going away */
mono_thread_suspend_all_other_threads ();
mono_vtable_set_is_remote (vtable, enable);
}
+
+#else /* DISABLE_REMOTING */
+
+ICALL_EXPORT void
+ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
+{
+ g_assert_not_reached ();
+}
+
#endif
ICALL_EXPORT MonoObject *
ICALL_EXPORT MonoBoolean
ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
{
- return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
+ return mono_is_debugger_attached ();
}
ICALL_EXPORT MonoBoolean
#endif /* DISABLE_ICALL_TABLES */
+static mono_mutex_t icall_mutex;
static GHashTable *icall_hash = NULL;
static GHashTable *jit_icall_hash_name = NULL;
static GHashTable *jit_icall_hash_addr = NULL;
#endif
icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ mono_mutex_init (&icall_mutex);
+}
+
+static void
+mono_icall_lock (void)
+{
+ mono_locks_mutex_acquire (&icall_mutex, IcallLock);
+}
+
+static void
+mono_icall_unlock (void)
+{
+ mono_locks_mutex_release (&icall_mutex, IcallLock);
}
void
g_hash_table_destroy (icall_hash);
g_hash_table_destroy (jit_icall_hash_name);
g_hash_table_destroy (jit_icall_hash_addr);
+ mono_mutex_destroy (&icall_mutex);
}
void
mono_add_internal_call (const char *name, gconstpointer method)
{
- mono_loader_lock ();
+ mono_icall_lock ();
g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
- mono_loader_unlock ();
+ mono_icall_unlock ();
}
#ifndef DISABLE_ICALL_TABLES
static gpointer
find_method_icall (const IcallTypeDesc *imap, const char *name)
{
- const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
+ const guint16 *nameslot = mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
if (!nameslot)
return NULL;
return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
static const IcallTypeDesc*
find_class_icalls (const char *name)
{
- const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
+ const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
if (!nameslot)
return NULL;
return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
static gpointer
find_method_icall (const IcallTypeDesc *imap, const char *name)
{
- const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
+ const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
if (!nameslot)
return NULL;
return (gpointer)icall_functions [(nameslot - icall_names)];
static const IcallTypeDesc*
find_class_icalls (const char *name)
{
- const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
+ const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
if (!nameslot)
return NULL;
return &icall_type_descs [nameslot - icall_type_names];
sigstart [siglen + 2] = 0;
g_free (tmpsig);
- mono_loader_lock ();
+ mono_icall_lock ();
res = g_hash_table_lookup (icall_hash, mname);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();;
return res;
}
/* try without signature */
*sigstart = 0;
res = g_hash_table_lookup (icall_hash, mname);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
#ifdef DISABLE_ICALL_TABLES
- mono_loader_unlock ();
+ mono_icall_unlock ();
/* Fail only when the result is actually used */
/* mono_marshal_get_native_wrapper () depends on this */
if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
#else
/* it wasn't found in the static call tables */
if (!imap) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return NULL;
}
res = find_method_icall (imap, sigstart - mlen);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
/* try _with_ signature */
*sigstart = '(';
res = find_method_icall (imap, sigstart - mlen);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
g_print ("If you see other errors or faults after this message they are probably related\n");
g_print ("and you need to fix your mono install first.\n");
- mono_loader_unlock ();
+ mono_icall_unlock ();
return NULL;
#endif
func = mono_lookup_internal_call (m);
if (!func)
return NULL;
- slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
+ slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
if (!slot)
return NULL;
g_assert (slot);
return &klass->byval_arg;
}
+/**
+ * LOCKING: Take the corlib image lock.
+ */
MonoMethodSignature*
mono_create_icall_signature (const char *sigstr)
{
gchar **parts;
int i, len;
gchar **tmp;
- MonoMethodSignature *res;
+ MonoMethodSignature *res, *res2;
+ MonoImage *corlib = mono_defaults.corlib;
- mono_loader_lock ();
- res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
- if (res) {
- mono_loader_unlock ();
+ mono_image_lock (corlib);
+ res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
+ mono_image_unlock (corlib);
+
+ if (res)
return res;
- }
parts = g_strsplit (sigstr, " ", 256);
tmp ++;
}
- res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
+ res = mono_metadata_signature_alloc (corlib, len - 1);
res->pinvoke = 1;
#ifdef HOST_WIN32
g_strfreev (parts);
- g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
-
- mono_loader_unlock ();
+ mono_image_lock (corlib);
+ res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
+ if (res2)
+ res = res2; /*Value is allocated in the image pool*/
+ else
+ g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
+ mono_image_unlock (corlib);
return res;
}
MonoJitICallInfo *info;
g_assert (jit_icall_hash_name);
- mono_loader_lock ();
+ mono_icall_lock ();
info = g_hash_table_lookup (jit_icall_hash_name, name);
- mono_loader_unlock ();
+ mono_icall_unlock ();
return info;
}
MonoJitICallInfo *info;
g_assert (jit_icall_hash_addr);
- mono_loader_lock ();
+ mono_icall_lock ();
info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
- mono_loader_unlock ();
+ mono_icall_unlock ();
return info;
}
* mono_get_jit_icall_info:
*
* Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
- * caller should access it while holding the loader lock.
+ * caller should access it while holding the icall lock.
*/
GHashTable*
mono_get_jit_icall_info (void)
MonoJitICallInfo *info;
const char *res = NULL;
- mono_loader_lock ();
+ mono_icall_lock ();
info = g_hash_table_lookup (jit_icall_hash_name, name);
if (info)
res = info->c_symbol;
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
void
mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
{
- mono_loader_lock ();
+ mono_icall_lock ();
g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
- mono_loader_unlock ();
+ mono_icall_unlock ();
}
MonoJitICallInfo *
g_assert (func);
g_assert (name);
- mono_loader_lock ();
+ mono_icall_lock ();
if (!jit_icall_hash_name) {
jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
- mono_loader_unlock ();
+ mono_icall_unlock ();
return info;
}