* Dietmar Maurer (dietmar@ximian.com)
* Paolo Molaro (lupus@ximian.com)
* Patrik Torstensson (patrik.torstensson@labs2.com)
+ * Marek Safar (marek.safar@gmail.com)
*
* Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
* Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
+ * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
*/
#include <config.h>
#include <mono/metadata/mono-ptr-array.h>
#include <mono/metadata/verify-internals.h>
#include <mono/metadata/runtime.h>
+#include <mono/metadata/file-mmap.h>
#include <mono/io-layer/io-layer.h>
#include <mono/utils/strtod.h>
#include <mono/utils/monobitset.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>
+#include <mono/utils/mono-threads.h>
#if defined (HOST_WIN32)
#include <windows.h>
MONO_ARCH_SAVE_REGS;
-#ifdef __arm__
- if (*ptr)
- *result = strtod (ptr, &endptr);
-#else
if (*ptr){
/* mono_strtod () is not thread-safe */
- EnterCriticalSection (&mono_strtod_mutex);
+ mono_mutex_lock (&mono_strtod_mutex);
*result = mono_strtod (ptr, &endptr);
- LeaveCriticalSection (&mono_strtod_mutex);
+ mono_mutex_unlock (&mono_strtod_mutex);
}
-#endif
if (!*ptr || (endptr && *endptr))
return FALSE;
}
if (!value) {
- mono_gc_bzero (ea, esize);
+ mono_gc_bzero_atomic (ea, esize);
return;
}
if (ec->has_references)
mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
else
- mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
+ mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
return;
}
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_atomic (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);
- mono_gc_memmove (dest_addr, source_addr, element_size * length);
+ dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
+ mono_gc_memmove_atomic (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;
esize = mono_array_element_size (ac);
ea = (gpointer*)((char*)ao->vector + (pos * esize));
- mono_gc_memmove (value, ea, esize);
+ mono_gc_memmove_atomic (value, ea, esize);
}
ICALL_EXPORT void
if (ec->has_references)
mono_gc_wbarrier_value_copy (ea, value, 1, ec);
else
- mono_gc_memmove (ea, value, esize);
+ mono_gc_memmove_atomic (ea, value, esize);
}
}
ICALL_EXPORT void
ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
{
- MONO_ARCH_SAVE_REGS;
+ MonoError error;
mono_image_check_for_module_cctor (image);
if (image->has_module_cctor) {
- MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
+ MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
+ mono_error_raise_exception (&error);
/*It's fine to raise the exception here*/
mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
}
size_t stack_size;
/* later make this configurable and per-arch */
int min_size = 4096 * 4 * sizeof (void*);
- mono_thread_get_stack_bounds (&stack_addr, &stack_size);
+ mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
/* if we have no info we are optimistic and assume there is enough room */
if (!stack_addr)
return TRUE;
+#ifdef HOST_WIN32
+ // FIXME: Windows dynamically extends the stack, so stack_addr might be close
+ // to the current sp
+ return TRUE;
+#endif
current = (guint8 *)&stack_addr;
if (current > stack_addr) {
if ((current - stack_addr) < min_size)
MonoObject **values = NULL;
MonoObject *o;
int count = 0;
- gint32 result = 0;
+ gint32 result = (int)(gsize)mono_defaults.int32_class;
MonoClassField* field;
gpointer iter;
klass = mono_object_class (this);
if (mono_class_num_fields (klass) == 0)
- return mono_object_hash (this);
+ return result;
/*
* Compute the starting value of the hashcode for fields of primitive
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;
static MonoReflectionType *
type_from_name (const char *str, MonoBoolean ignoreCase)
{
+ MonoMethod *m, *dest;
+
MonoType *type = NULL;
MonoAssembly *assembly = NULL;
MonoTypeNameParse info;
return NULL;
}
- if (info.assembly.name) {
- assembly = mono_assembly_load (&info.assembly, NULL, NULL);
- } else {
- MonoMethod *m = mono_method_get_last_managed ();
- MonoMethod *dest = m;
- mono_stack_walk_no_il (get_caller_no_reflection, &dest);
- if (!dest)
- dest = m;
+ /*
+ * We must compute the calling assembly as type loading must happen under a metadata context.
+ * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
+ * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
+ */
+ m = mono_method_get_last_managed ();
+ dest = m;
- /*
- * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
- * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
- * to crash. This only seems to happen in some strange remoting
- * scenarios and I was unable to figure out what's happening there.
- * Dec 10, 2005 - Martin.
- */
+ mono_stack_walk_no_il (get_caller_no_reflection, &dest);
+ if (!dest)
+ dest = m;
- if (dest) {
- assembly = dest->klass->image->assembly;
- type_resolve = TRUE;
- } else {
- g_warning (G_STRLOC);
- }
+ /*
+ * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
+ * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
+ * to crash. This only seems to happen in some strange remoting
+ * scenarios and I was unable to figure out what's happening there.
+ * Dec 10, 2005 - Martin.
+ */
+
+ if (dest) {
+ assembly = dest->klass->image->assembly;
+ type_resolve = TRUE;
+ } else {
+ g_warning (G_STRLOC);
}
+ if (info.assembly.name)
+ assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
+
+
if (assembly) {
/* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
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)
klass = mono_class_from_mono_type (type->type);
klassc = mono_class_from_mono_type (c->type);
- mono_class_init_or_throw (klass);
- mono_class_init_or_throw (klassc);
-
if (type->type->byref ^ c->type->byref)
return FALSE;
{
MonoClass *klass = field->field->parent;
MonoMarshalType *info;
+ MonoType *ftype;
int i;
if (klass->generic_container ||
(klass->generic_class && klass->generic_class->context.class_inst->is_open))
return NULL;
+ ftype = mono_field_get_type (field->field);
+ if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
+ return NULL;
+
info = mono_marshal_load_type_info (klass);
for (i = 0; i < info->num_fields; ++i) {
{
MonoError error;
MonoType *type = mono_field_get_type_checked (field->field, &error);
- if (!mono_error_ok (&error))
- mono_error_raise_exception (&error);
+ mono_error_raise_exception (&error);
return type_array_from_modifiers (field->field->parent->image, type, optional);
}
MonoClass *parent = field->field->parent;
if (!parent->size_inited)
mono_class_init (parent);
+ mono_class_setup_fields_locking (parent);
return field->field->offset - sizeof (MonoObject);
}
if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
mono_raise_exception (mono_get_exception_invalid_operation (NULL));
- if (field->parent->image->dynamic) {
- /* FIXME: */
- g_assert_not_reached ();
+ if (image_is_dynamic (field->parent->image)) {
+ MonoClass *klass = field->parent;
+ int fidx = field - klass->fields;
+
+ g_assert (fidx >= 0 && fidx < klass->field.count);
+ g_assert (klass->ext);
+ g_assert (klass->ext->field_def_values);
+ def_type = klass->ext->field_def_values [fidx].def_type;
+ def_value = klass->ext->field_def_values [fidx].data;
+ if (def_type == MONO_TYPE_END)
+ mono_raise_exception (mono_get_exception_invalid_operation (NULL));
+ } else {
+ def_value = mono_class_get_field_default_value (field, &def_type);
+ /* FIXME, maybe we should try to raise TLE if field->parent is broken */
+ if (!def_value)
+ mono_raise_exception (mono_get_exception_invalid_operation (NULL));
}
- def_value = mono_class_get_field_default_value (field, &def_type);
- if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
- mono_raise_exception (mono_get_exception_invalid_operation (NULL));
-
/*FIXME unify this with reflection.c:mono_get_object_from_blob*/
switch (def_type) {
case MONO_TYPE_U1:
MonoClass *klass = mono_class_from_mono_type (type->type);
mono_class_init_or_throw (klass);
- if (klass->image->dynamic) {
+ if (image_is_dynamic (klass->image)) {
MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
*packing = tb->packing_size;
*size = tb->class_size;
if (type->type->byref)
return NULL;
- if (type->type->type == MONO_TYPE_VAR)
- class = mono_type_get_generic_param_owner (type->type)->owner.klass;
- else if (type->type->type == MONO_TYPE_MVAR)
- class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
- else
+ if (type->type->type == MONO_TYPE_VAR) {
+ MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
+ class = param ? param->owner.klass : NULL;
+ } else if (type->type->type == MONO_TYPE_MVAR) {
+ MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
+ class = param ? param->owner.method->klass : NULL;
+ } else {
class = mono_class_from_mono_type (type->type)->nested_in;
+ }
return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
}
g_assert (DllImportAttributeClass);
}
- if (method->klass->image->dynamic) {
+ if (image_is_dynamic (method->klass->image)) {
MonoReflectionMethodAux *method_aux =
g_hash_table_lookup (
((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
if (!result->is_generic)
return NULL;
- if (method->method->klass->image->dynamic) {
+ if (image_is_dynamic (method->method->klass->image)) {
MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
MonoReflectionMethod *res;
* 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_is_dynamic (image) && !((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;
for (i = 0; i < pcount; ++i)
lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
+ if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
+ /* This is a ctor for jagged arrays. MS creates an array of arrays. */
+ MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
+
+ for (i = 0; i < mono_array_length (arr); ++i) {
+ MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
+
+ mono_array_setref_fast (arr, i, subarray);
+ }
+ return (MonoObject*)arr;
+ }
+
if (m->klass->rank == pcount) {
/* Only lengths provided. */
lower_bounds = NULL;
read_enum_value (char *mem, int type)
{
switch (type) {
+ case MONO_TYPE_BOOLEAN:
case MONO_TYPE_U1:
return *(guint8*)mem;
case MONO_TYPE_I1:
return *(gint8*)mem;
+ case MONO_TYPE_CHAR:
case MONO_TYPE_U2:
return *(guint16*)mem;
case MONO_TYPE_I2:
if (!enumc->enumtype)
mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
- if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
+ if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_BOOLEAN && objc->byval_arg.type <= MONO_TYPE_U8)))
mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
etype = mono_class_enum_basetype (enumc);
return me > other ? 1 : -1; \
} while (0)
-#define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
- ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
- ENUM_TYPE other = *((ENUM_TYPE*)odata); \
- if (me == other) \
- return 0; \
- return me - other; \
- } while (0)
-
switch (basetype->type) {
case MONO_TYPE_U1:
COMPARE_ENUM_VALUES (guint8);
COMPARE_ENUM_VALUES (gint8);
case MONO_TYPE_CHAR:
case MONO_TYPE_U2:
- COMPARE_ENUM_VALUES_RANGE (guint16);
+ COMPARE_ENUM_VALUES (guint16);
case MONO_TYPE_I2:
COMPARE_ENUM_VALUES (gint16);
case MONO_TYPE_U4:
default:
g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
}
-#undef COMPARE_ENUM_VALUES_RANGE
#undef COMPARE_ENUM_VALUES
return 0;
}
return NULL;
}
+static guint
+event_hash (gconstpointer data)
+{
+ MonoEvent *event = (MonoEvent*)data;
+
+ return g_str_hash (event->name);
+}
+
+static gboolean
+event_equal (MonoEvent *event1, MonoEvent *event2)
+{
+ // Events are hide-by-name
+ return g_str_equal (event1->name, event2->name);
+}
+
ICALL_EXPORT MonoArray*
ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
{
MonoEvent *event;
int i, match;
gpointer iter;
-
+ GHashTable *events = NULL;
MonoPtrArray tmp_array;
MONO_ARCH_SAVE_REGS;
return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
klass = startklass = mono_class_from_mono_type (type->type);
+ events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
handle_parent:
mono_class_setup_vtable (klass);
if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
match ++;
if (!match)
continue;
+
+ if (g_hash_table_lookup (events, event))
+ continue;
+
mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
+
+ g_hash_table_insert (events, event, event);
}
if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
goto handle_parent;
+ g_hash_table_destroy (events);
+
res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
type = NULL;
}
else
- if (assembly->assembly->dynamic) {
+ if (assembly_is_dynamic (assembly->assembly)) {
/* Enumerate all modules */
MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
int i;
MonoImage *image = assembly->assembly->image;
g_assert (image != NULL);
- g_assert (!assembly->assembly->dynamic);
+ g_assert (!assembly_is_dynamic (assembly->assembly));
table = &image->tables [MONO_TABLE_FILE];
file_count = table->rows;
attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
- klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
+ MonoError error;
+ klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
+ g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */
+
if (klass) {
mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
} else {
- MonoLoaderError *error;
- MonoException *ex;
-
- error = mono_loader_get_last_error ();
- g_assert (error != NULL);
-
- ex = mono_loader_error_prepare_exception (error);
+ MonoException *ex = mono_error_convert_to_exception (&error);
mono_array_setref (*exceptions, count, ex);
}
- if (mono_loader_get_last_error ())
- mono_loader_clear_error ();
count++;
}
}
domain = mono_object_domain (assembly);
- g_assert (!assembly->assembly->dynamic);
+ g_assert (!assembly_is_dynamic (assembly->assembly));
image = assembly->assembly->image;
table = &image->tables [MONO_TABLE_FILE];
res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
mono_loader_clear_error ();
exl = mono_array_new (domain, mono_defaults.exception_class, length);
- /* Types for which mono_class_get () succeeded */
+ /* Types for which mono_class_get_checked () succeeded */
for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
mono_array_setref (exl, i, exc);
ICALL_EXPORT MonoReflectionType*
ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
{
+ MonoError error;
MonoDomain *domain = mono_object_domain (module);
MonoClass *klass;
g_assert (module->image);
- if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
+ if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
/* These images do not have a global type */
return NULL;
- klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
+ klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
+ mono_error_raise_exception (&error);
return mono_type_get_object (domain, &klass->byval_arg);
}
ICALL_EXPORT void
ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
{
- if (image->dynamic) {
+ if (image_is_dynamic (image)) {
MonoDynamicImage *dyn = (MonoDynamicImage*)image;
*pe_kind = dyn->pe_kind;
*machine = dyn->machine;
static gboolean
mono_memberref_is_method (MonoImage *image, guint32 token)
{
- if (!image->dynamic) {
+ if (!image_is_dynamic (image)) {
guint32 cols [MONO_MEMBERREF_SIZE];
const char *sig;
mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
}
ICALL_EXPORT MonoType*
-ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
+ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
{
MonoClass *klass;
int table = mono_metadata_token_table (token);
int index = mono_metadata_token_index (token);
MonoGenericContext context;
+ MonoError error;
- *error = ResolveTokenError_Other;
+ *resolve_error = ResolveTokenError_Other;
/* Validate token */
if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
(table != MONO_TABLE_TYPESPEC)) {
- *error = ResolveTokenError_BadTable;
+ *resolve_error = ResolveTokenError_BadTable;
return NULL;
}
- if (image->dynamic) {
+ if (image_is_dynamic (image)) {
if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
return klass ? &klass->byval_arg : NULL;
}
if ((index <= 0) || (index > image->tables [table].rows)) {
- *error = ResolveTokenError_OutOfRange;
+ *resolve_error = ResolveTokenError_OutOfRange;
return NULL;
}
init_generic_context_from_args (&context, type_args, method_args);
- klass = mono_class_get_full (image, token, &context);
-
- if (mono_loader_get_last_error ())
- mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
+ klass = mono_class_get_checked (image, token, &error);
+ if (klass)
+ klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
+ mono_error_raise_exception (&error);
if (klass)
return &klass->byval_arg;
return NULL;
}
- if (image->dynamic) {
+ if (image_is_dynamic (image)) {
if (table == MONO_TABLE_METHOD)
return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
return NULL;
}
- if (image->dynamic)
+ if (image_is_dynamic (image))
return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
if ((index <= 0) || (index >= image->heap_us.size)) {
}
ICALL_EXPORT MonoClassField*
-ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
+ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
{
+ MonoError error;
MonoClass *klass;
int table = mono_metadata_token_table (token);
int index = mono_metadata_token_index (token);
MonoGenericContext context;
MonoClassField *field;
- *error = ResolveTokenError_Other;
+ *resolve_error = ResolveTokenError_Other;
/* Validate token */
if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
- *error = ResolveTokenError_BadTable;
+ *resolve_error = ResolveTokenError_BadTable;
return NULL;
}
- if (image->dynamic) {
+ if (image_is_dynamic (image)) {
if (table == MONO_TABLE_FIELD)
return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
if (mono_memberref_is_method (image, token)) {
- *error = ResolveTokenError_BadTable;
+ *resolve_error = ResolveTokenError_BadTable;
return NULL;
}
}
if ((index <= 0) || (index > image->tables [table].rows)) {
- *error = ResolveTokenError_OutOfRange;
+ *resolve_error = ResolveTokenError_OutOfRange;
return NULL;
}
if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
- *error = ResolveTokenError_BadTable;
+ *resolve_error = ResolveTokenError_BadTable;
return NULL;
}
init_generic_context_from_args (&context, type_args, method_args);
- field = mono_field_from_token (image, token, &klass, &context);
-
- if (mono_loader_get_last_error ())
- mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
+ field = mono_field_from_token_checked (image, token, &klass, &context, &error);
+ mono_error_raise_exception (&error);
return field;
}
if (table != MONO_TABLE_STANDALONESIG)
return NULL;
- if (image->dynamic)
+ if (image_is_dynamic (image))
return NULL;
if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
delegate = mono_object_new (mono_object_domain (type), delegate_class);
- if (method->dynamic) {
+ if (method_is_dynamic (method)) {
/* Creating a trampoline would leak memory */
func = mono_compile_method (method);
} else {
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));
#endif
}
-ICALL_EXPORT gpointer
-ves_icall_System_Object_obj_address (MonoObject *this)
-{
- MONO_ARCH_SAVE_REGS;
-
- return this;
-}
-
/* System.Buffer */
static inline gint32
if (src != dest)
memcpy (dest_buf, src_buf, count);
else
- mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
+ memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
return TRUE;
}
ICALL_EXPORT void
ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
{
- MonoError error;
#ifdef HOST_WIN32
-
gunichar2 *utf16_name, *utf16_value;
#else
gchar *utf8_name, *utf8_value;
+ MonoError error;
#endif
MONO_ARCH_SAVE_REGS;
{
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.
ves_icall_System_Environment_BroadcastSettingChange (void)
{
#ifdef HOST_WIN32
- SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
+ SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
#endif
}
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
*to_upper_data_high = ToUpperDataHigh;
}
-ICALL_EXPORT gint32
-ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
-{
- return method->method->token;
-}
-
/*
* We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
* and avoid useless allocations.
+ *
+ * MAY THROW
*/
static MonoArray*
type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
count = 0;
for (i = 0; i < type->num_mods; ++i) {
if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
- MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
+ MonoError error;
+ MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
+ mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
count++;
}
mono_class_init_or_throw (attr_class);
res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
- if (!mono_error_ok (&error))
- mono_error_raise_exception (&error);
+ mono_error_raise_exception (&error);
+
if (mono_loader_get_last_error ()) {
mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
g_assert_not_reached ();
#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
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
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;
}