Merge pull request #505 from roji/shutdown_flow
[mono.git] / mono / metadata / icall.c
index b7873f5caac24caff2929e27b66d827fda96bb39..ed34f324fc96e03b17aa06a093c71102e58b846a 100644 (file)
@@ -8,7 +8,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
- * Copyright 2011 Xamarin Inc (http://www.xamarin.com).
+ * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
  */
 
 #include <config.h>
@@ -73,6 +73,7 @@
 #include <mono/metadata/mono-debug.h>
 #include <mono/metadata/mono-ptr-array.h>
 #include <mono/metadata/verify-internals.h>
+#include <mono/metadata/runtime.h>
 #include <mono/io-layer/io-layer.h>
 #include <mono/utils/strtod.h>
 #include <mono/utils/monobitset.h>
@@ -82,6 +83,7 @@
 #include <mono/utils/mono-error-internals.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-io-portability.h>
+#include <mono/utils/mono-digest.h>
 
 #if defined (HOST_WIN32)
 #include <windows.h>
@@ -1168,10 +1170,12 @@ ves_icall_System_Object_GetType (MonoObject *obj)
 {
        MONO_ARCH_SAVE_REGS;
 
-       if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
-               return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
-       else
+#ifndef DISABLE_REMOTING
+       if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
                return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
+       else
+#endif
+               return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
 }
 
 ICALL_EXPORT void
@@ -1641,8 +1645,8 @@ ves_icall_get_attributes (MonoReflectionType *type)
        return klass->flags;
 }
 
-ICALL_EXPORT MonoReflectionMarshal*
-ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
+ICALL_EXPORT MonoReflectionMarshalAsAttribute*
+ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
 {
        MonoClass *klass = field->field->parent;
        MonoMarshalType *info;
@@ -1659,7 +1663,7 @@ ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *
                        if (!info->fields [i].mspec)
                                return NULL;
                        else
-                               return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
+                               return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
                }
        }
 
@@ -1749,11 +1753,11 @@ ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
        return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
 }
 
-ICALL_EXPORT MonoReflectionMarshal*
+ICALL_EXPORT MonoReflectionMarshalAsAttribute*
 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
 {
        MonoDomain *domain = mono_domain_get (); 
-       MonoReflectionMarshal* res = NULL;
+       MonoReflectionMarshalAsAttribute* res = NULL;
        MonoMarshalSpec **mspecs;
        int i;
 
@@ -1761,7 +1765,7 @@ ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
        mono_method_get_marshal_info (method, mspecs);
 
        if (mspecs [0])
-               res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
+               res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
                
        for (i = mono_method_signature (method)->param_count; i >= 0; i--)
                if (mspecs [i])
@@ -2875,6 +2879,7 @@ ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoAr
        return mono_runtime_invoke_array (m, obj, params, NULL);
 }
 
+#ifndef DISABLE_REMOTING
 ICALL_EXPORT MonoObject *
 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs) 
 {
@@ -3002,6 +3007,7 @@ ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoA
 
        return result;
 }
+#endif
 
 static guint64
 read_enum_value (char *mem, int type)
@@ -4533,53 +4539,6 @@ ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAsse
        return result;
 }
 
-typedef struct {
-       MonoArray *res;
-       int idx;
-} NameSpaceInfo;
-
-static void
-foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
-{
-       MonoString *name = mono_string_new (mono_object_domain (info->res), key);
-
-       mono_array_setref (info->res, info->idx, name);
-       info->idx++;
-}
-
-ICALL_EXPORT MonoArray*
-ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly) 
-{
-       MonoImage *img = assembly->assembly->image;
-       MonoArray *res;
-       NameSpaceInfo info;
-       int len;
-
-       MONO_ARCH_SAVE_REGS;
-
-       mono_image_lock (img);
-       mono_image_init_name_cache (img);
-
-RETRY_LEN:
-       len = g_hash_table_size (img->name_cache);
-       mono_image_unlock (img);
-
-       /*we can't create objects holding the image lock */
-       res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
-
-       mono_image_lock (img);
-       /*len might have changed, create a new array*/
-       if (len != g_hash_table_size (img->name_cache))
-               goto RETRY_LEN;
-
-       info.res = res;
-       info.idx = 0;
-       g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
-       mono_image_unlock (img);
-
-       return res;
-}
-
 /* move this in some file in mono/util/ */
 static char *
 g_concat_dir_and_file (const char *dir, const char *file)
@@ -6254,6 +6213,10 @@ ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, Mo
 
        MONO_ARCH_SAVE_REGS;
 
+       /* This is called directly from the class libraries without going through the managed wrapper */
+       MONO_CHECK_ARG_NULL (src);
+       MONO_CHECK_ARG_NULL (dest);
+
        /* watch out for integer overflow */
        if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
                return FALSE;
@@ -6269,6 +6232,7 @@ ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, Mo
        return TRUE;
 }
 
+#ifndef DISABLE_REMOTING
 ICALL_EXPORT MonoObject *
 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
 {
@@ -6300,6 +6264,7 @@ ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
 {
        return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
 }
+#endif
 
 /* System.Environment */
 
@@ -6565,6 +6530,10 @@ ves_icall_System_Environment_Exit (int result)
 {
        MONO_ARCH_SAVE_REGS;
 
+#ifndef MONO_CROSS_COMPILE
+       mono_runtime_shutdown ();
+#endif
+
        mono_threads_set_shutting_down ();
 
        mono_runtime_set_shutting_down ();
@@ -6788,6 +6757,7 @@ ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
        mono_message_init (mono_object_domain (this), this, method, out_args);
 }
 
+#ifndef DISABLE_REMOTING
 ICALL_EXPORT MonoBoolean
 ves_icall_IsTransparentProxy (MonoObject *proxy)
 {
@@ -6868,6 +6838,7 @@ ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (Mo
        if (enable) vtable->remote = 1;
        else vtable->remote = 0;
 }
+#endif
 
 ICALL_EXPORT MonoObject *
 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
@@ -7674,6 +7645,7 @@ base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespac
        gint a [4], b [4];
        MonoException *exc;
 
+       int havePadding = 0;
        ignored = 0;
        last = prev_last = 0, prev2_last = 0;
        for (i = 0; i < ilength; i++) {
@@ -7685,7 +7657,13 @@ base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespac
                        mono_raise_exception (exc);
                } else if (isspace (c)) {
                        ignored++;
+               } else if (havePadding && c != '=') {
+                       exc = mono_exception_from_name_msg (mono_get_corlib (),
+                               "System", "FormatException",
+                               "Invalid character found.");
+                       mono_raise_exception (exc);
                } else {
+                       if (c == '=') havePadding = 1;
                        prev2_last = prev_last;
                        prev_last = last;
                        last = c;
@@ -8048,11 +8026,13 @@ concat_class_name (char *buf, int bufsize, MonoClass *klass)
        return nspacelen + cnamelen;
 }
 
+#ifdef DISABLE_ICALL_TABLES
 static void
 no_icall_table (void)
 {
        g_assert_not_reached ();
 }
+#endif
 
 gpointer
 mono_lookup_internal_call (MonoMethod *method)
@@ -8063,7 +8043,7 @@ mono_lookup_internal_call (MonoMethod *method)
        int typelen = 0, mlen, siglen;
        gpointer res;
 #ifndef DISABLE_ICALL_TABLES
-       const IcallTypeDesc *imap;
+       const IcallTypeDesc *imap = NULL;
 #endif
 
        g_assert (method != NULL);
@@ -8090,6 +8070,10 @@ mono_lookup_internal_call (MonoMethod *method)
                        return NULL;
        }
 
+#ifndef DISABLE_ICALL_TABLES
+       imap = find_class_icalls (mname);
+#endif
+
        mname [typelen] = ':';
        mname [typelen + 1] = ':';
 
@@ -8126,10 +8110,12 @@ mono_lookup_internal_call (MonoMethod *method)
 #ifdef DISABLE_ICALL_TABLES
        mono_loader_unlock ();
        /* Fail only when the result is actually used */
-       return no_icall_table;
+       /* mono_marshal_get_native_wrapper () depends on this */
+       if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
+               return ves_icall_System_String_ctor_RedirectToCreateString;
+       else
+               return no_icall_table;
 #else
-       imap = find_class_icalls (mname);
-
        /* it wasn't found in the static call tables */
        if (!imap) {
                mono_loader_unlock ();
@@ -8162,11 +8148,13 @@ mono_lookup_internal_call (MonoMethod *method)
 #endif
 }
 
+#ifdef ENABLE_ICALL_SYMBOL_MAP
 static int
 func_cmp (gconstpointer key, gconstpointer p)
 {
        return (gsize)key - (gsize)*(gsize*)p;
 }
+#endif
 
 /*
  * mono_lookup_icall_symbol:
@@ -8365,6 +8353,25 @@ mono_get_jit_icall_info (void)
        return jit_icall_hash_name;
 }
 
+/*
+ * mono_lookup_jit_icall_symbol:
+ *
+ *   Given the jit icall NAME, returns its C symbol if possible, or NULL.
+ */
+const char*
+mono_lookup_jit_icall_symbol (const char *name)
+{
+       MonoJitICallInfo *info;
+       const char *res = NULL;
+
+       mono_loader_lock ();
+       info = g_hash_table_lookup (jit_icall_hash_name, name);
+       if (info)
+               res = info->c_symbol;
+       mono_loader_unlock ();
+       return res;
+}
+
 void
 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
 {
@@ -8374,7 +8381,7 @@ mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
 }
 
 MonoJitICallInfo *
-mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
+mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
 {
        MonoJitICallInfo *info;
        
@@ -8398,6 +8405,7 @@ mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignatu
        info->name = name;
        info->func = func;
        info->sig = sig;
+       info->c_symbol = c_symbol;
 
        if (is_save) {
                info->wrapper = func;
@@ -8411,3 +8419,10 @@ mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignatu
        mono_loader_unlock ();
        return info;
 }
+
+MonoJitICallInfo *
+mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
+{
+       return mono_register_jit_icall_full (func, name, sig, is_save, NULL);
+}
+