2010-03-12 Jb Evain <jbevain@novell.com>
[mono.git] / mono / metadata / icall.c
index 04bb294b04f0d32fca9778c349cddf0822d5f4cc..d1f2bb0806f481647c130c7795941c23bc48031d 100644 (file)
@@ -74,6 +74,7 @@
 #include <mono/utils/mono-proclib.h>
 #include <mono/utils/mono-string.h>
 #include <mono/utils/mono-error-internals.h>
+#include <mono/utils/mono-mmap.h>
 
 #if defined (HOST_WIN32)
 #include <windows.h>
@@ -81,6 +82,8 @@
 #endif
 #include "decimal.h"
 
+extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
+
 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
 
 static MonoArray*
@@ -259,6 +262,11 @@ ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32
        ea = (gpointer*)((char*)this->vector + (pos * esize));
        va = (gpointer*)((char*)value + sizeof (MonoObject));
 
+       if (mono_class_is_nullable (ec)) {
+               mono_nullable_init ((guint8*)ea, value, ec);
+               return;
+       }
+
        if (!value) {
                memset (ea, 0,  esize);
                return;
@@ -972,6 +980,29 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (M
        }
 }
 
+static MonoBoolean
+ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
+{
+       guint8 *stack_addr;
+       guint8 *current;
+       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);
+       /* if we have no info we are optimistic and assume there is enough room */
+       if (!stack_addr)
+               return TRUE;
+       current = (guint8 *)&stack_addr;
+       if (current > stack_addr) {
+               if ((current - stack_addr) < min_size)
+                       return FALSE;
+       } else {
+               if (current - (stack_addr - stack_size) < min_size)
+                       return FALSE;
+       }
+       return TRUE;
+}
+
 static MonoObject *
 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
 {
@@ -1319,19 +1350,27 @@ type_from_name (const char *str, MonoBoolean ignoreCase)
                 *        Dec 10, 2005 - Martin.
                 */
 
-               if (dest)
+               if (dest) {
                        assembly = dest->klass->image->assembly;
-               else {
+                       type_resolve = TRUE;
+               } else {
                        g_warning (G_STRLOC);
                }
        }
 
-       if (assembly)
+       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);
-       
+       }
+
        if (!info.assembly.name && !type) /* try mscorlib */
                type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
 
+       if (assembly && !type && type_resolve) {
+               type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
+               type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
+       }
+
        mono_reflection_free_type_info (&info);
        g_free (temp_str);
 
@@ -1944,6 +1983,7 @@ ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
 
        def_value = mono_class_get_field_default_value (field, &def_type);
 
+       /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
        switch (def_type) {
        case MONO_TYPE_U1:
        case MONO_TYPE_I1:
@@ -2047,6 +2087,7 @@ ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
        MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
        MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
 
+#ifndef MONO_SMALL_CONFIG
        if (event->event->other) {
                int i, n = 0;
                while (event->event->other [n])
@@ -2056,11 +2097,13 @@ ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
                for (i = 0; i < n; i++)
                        mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
        }               
+#endif
 }
 
 static MonoArray*
 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
 {
+       MonoError error;
        MonoDomain *domain = mono_object_domain (type); 
        MonoArray *intf;
        GPtrArray *ifaces = NULL;
@@ -2082,8 +2125,12 @@ ves_icall_Type_GetInterfaces (MonoReflectionType* type)
        slots = mono_bitset_new (class->max_interface_id + 1, 0);
 
        for (parent = class; parent; parent = parent->parent) {
-               GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
-               if (tmp_ifaces) {
+               GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
+               if (!mono_error_ok (&error)) {
+                       mono_bitset_free (slots);
+                       mono_error_raise_exception (&error);
+                       return NULL;
+               } else if (tmp_ifaces) {
                        for (i = 0; i < tmp_ifaces->len; ++i) {
                                MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
 
@@ -2122,6 +2169,7 @@ ves_icall_Type_GetInterfaces (MonoReflectionType* type)
 static void
 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
 {
+       gboolean variance_used;
        MonoClass *class = mono_class_from_mono_type (type->type);
        MonoClass *iclass = mono_class_from_mono_type (iface->type);
        MonoReflectionMethod *member;
@@ -2134,12 +2182,11 @@ ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType
 
        mono_class_setup_vtable (class);
 
-       /* type doesn't implement iface: the exception is thrown in managed code */
-       if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
-                       return;
+       ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
+       if (ioffset == -1)
+               return;
 
        len = mono_class_num_methods (iclass);
-       ioffset = mono_class_interface_offset (class, iclass);
        domain = mono_object_domain (type);
        mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
        mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
@@ -2403,9 +2450,12 @@ ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
        }
        if (klass->generic_class) {
                MonoClass *generic_class = klass->generic_class->container_class;
+               gpointer tb;
+
+               tb = mono_class_get_ref_info (generic_class);
 
-               if (generic_class->wastypebuilder && generic_class->reflection_info)
-                       return generic_class->reflection_info;
+               if (generic_class->wastypebuilder && tb)
+                       return tb;
                else
                        return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
        }
@@ -2688,7 +2738,9 @@ ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
 
        if (imethod->context.class_inst) {
                MonoClass *klass = ((MonoMethod *) imethod)->klass;
-               result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
+               /*Generic methods gets the context of the GTD.*/
+               if (mono_class_get_context (klass))
+                       result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
        }
 
        return mono_method_get_object (mono_object_domain (method), result, NULL);
@@ -3473,7 +3525,8 @@ handle_parent:
                        g_assert (method->slot < nslots);
                        if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
                                continue;
-                       method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
+                       if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
+                               method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
                }
 
                if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
@@ -4702,7 +4755,8 @@ ves_icall_GetCurrentMethod (void)
 {
        MonoMethod *m = mono_method_get_last_managed ();
 
-       MONO_ARCH_SAVE_REGS;
+       while (m->is_inflated)
+               m = ((MonoMethodInflated*)m)->declaring;
 
        return mono_method_get_object (mono_domain_get (), m, NULL);
 }
@@ -4726,6 +4780,8 @@ mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
        }
 
        mono_class_setup_methods (method->klass);
+       if (method->klass->exception_type)
+               return NULL;
        for (i = 0; i < method->klass->method.count; ++i) {
                if (method->klass->methods [i] == method) {
                        offset = i;
@@ -4733,6 +4789,8 @@ mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
                }       
        }
        mono_class_setup_methods (klass);
+       if (klass->exception_type)
+               return NULL;
        g_assert (offset >= 0 && offset < klass->method.count);
        return klass->methods [offset];
 }
@@ -4745,8 +4803,11 @@ ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMeth
                klass = mono_class_from_mono_type (type);
                if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass)) 
                        return NULL;
-               if (method->klass != klass)
+               if (method->klass != klass) {
                        method = mono_method_get_equivalent_method (method, klass);
+                       if (!method)
+                               return NULL;
+               }
        } else
                klass = method->klass;
        return mono_method_get_object (mono_domain_get (), method, klass);
@@ -4838,6 +4899,13 @@ ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full
        return res;
 }
 
+static int
+vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
+{
+       MonoClass *klass = mono_class_from_mono_type (this->type);
+       return mono_security_core_clr_class_level (klass);
+}
+
 static void
 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
 {
@@ -4969,14 +5037,14 @@ ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly,
        if (g_path_is_absolute (mass->image->name)) {
                fill_reflection_assembly_name (mono_object_domain (assembly),
                        aname, &mass->aname, mass->image->name, TRUE,
-                       TRUE, mono_framework_version () >= 2);
+                       TRUE, TRUE);
                return;
        }
        absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
 
        fill_reflection_assembly_name (mono_object_domain (assembly),
                aname, &mass->aname, absolute, TRUE, TRUE,
-               mono_framework_version () >= 2);
+               TRUE);
 
        g_free (absolute);
 }
@@ -5020,8 +5088,7 @@ ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname,
        }
 
        fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
-               TRUE, mono_framework_version () == 1,
-               mono_framework_version () >= 2);
+               TRUE, FALSE, TRUE);
 
        g_free (filename);
        mono_image_close (image);
@@ -6173,9 +6240,6 @@ ves_icall_System_Environment_get_Platform (void)
        return 2;
 #elif defined(__MACH__)
        /* OSX */
-       if (mono_framework_version () < 2)
-               return 128;
-
        //
        // For compatibility with our client code, this will be 4 for a while.
        // We will eventually move to 6 to match .NET, but it requires all client
@@ -6185,8 +6249,6 @@ ves_icall_System_Environment_get_Platform (void)
        return 4;
 #else
        /* Unix */
-       if (mono_framework_version () < 2)
-               return 128;
        return 4;
 #endif
 }
@@ -6645,7 +6707,9 @@ ves_icall_Remoting_RemotingServices_GetVirtualMethod (
        vtable = klass->vtable;
 
        if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
-               int offs = mono_class_interface_offset (klass, method->klass);
+               gboolean variance_used = FALSE;
+               /*MS fails with variant interfaces but it's the right thing to do anyway.*/
+               int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
                if (offs >= 0)
                        res = vtable [offs + method->slot];
        } else {
@@ -7174,10 +7238,32 @@ static MonoArray*
 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
 {
        MonoType *type = param->ClassImpl->type;
-       MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
-       MonoImage *image = method->method->klass->image;
-       int pos = param->PositionImpl;
-       MonoMethodSignature *sig = mono_method_signature (method->method);
+       MonoClass *member_class = mono_object_class (param->MemberImpl);
+       MonoMethod *method = NULL;
+       MonoImage *image;
+       int pos;
+       MonoMethodSignature *sig;
+
+       if (mono_class_is_reflection_method_or_constructor (member_class)) {
+               MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
+               method = rmethod->method;
+       } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
+               MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
+               if (!(method = prop->property->get))
+                       method = prop->property->set;
+               g_assert (method);      
+       } else {
+               char *type_name = mono_type_get_full_name (member_class);
+               char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
+               MonoException *ex = mono_get_exception_not_supported  (msg);
+               g_free (type_name);
+               g_free (msg);
+               mono_raise_exception (ex);
+       }
+
+       image = method->klass->image;
+       pos = param->PositionImpl;
+       sig = mono_method_signature (method);
        if (pos == -1)
                type = sig->ret;
        else
@@ -7211,6 +7297,54 @@ property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean
        return type_array_from_modifiers (image, type, optional);
 }
 
+/*
+ *Construct a MonoType suited to be used to decode a constant blob object.
+ *
+ * @type is the target type which will be constructed
+ * @blob_type is the blob type, for example, that comes from the constant table
+ * @real_type is the expected constructed type.
+ */
+static void
+mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
+{
+       type->type = blob_type;
+       type->data.klass = NULL;
+       if (blob_type == MONO_TYPE_CLASS)
+               type->data.klass = mono_defaults.object_class;
+       else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
+               /* For enums, we need to use the base type */
+               type->type = MONO_TYPE_VALUETYPE;
+               type->data.klass = mono_class_from_mono_type (real_type);
+       } else
+               type->data.klass = mono_class_from_mono_type (real_type);
+}
+
+static MonoObject*
+property_info_get_default_value (MonoReflectionProperty *property)
+{
+       MonoType blob_type;
+       MonoProperty *prop = property->property;
+       MonoType *type = get_property_type (prop);
+       MonoDomain *domain = mono_object_domain (property); 
+       MonoTypeEnum def_type;
+       const char *def_value;
+       MonoObject *o;
+
+       g_assert (!prop->parent->image->dynamic);
+
+       mono_class_init (prop->parent);
+
+       if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
+               mono_raise_exception (mono_get_exception_invalid_operation (NULL));
+
+       def_value = mono_class_get_property_default_value (prop, &def_type);
+
+       mono_type_from_blob_type (&blob_type, def_type, type);
+       o = mono_get_object_from_blob (domain, &blob_type, def_value);
+
+       return o;
+}
+
 static MonoBoolean
 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
 {
@@ -7253,6 +7387,12 @@ ves_icall_Mono_Runtime_GetDisplayName (void)
        return display_name;
 }
 
+static MonoObject *
+ves_icall_Mono_Runtime_NewObject (MonoType *t)
+{
+       return mono_object_new (mono_domain_get (), mono_class_from_mono_type (t));
+}
+
 static MonoString*
 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
 {