Mon Mar 25 13:04:56 CET 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / appdomain.c
index f0db534662c13c0e42c08a7746e011d2466a7f49..c2623daad31b2d1a8ac3b8ab884d7095e25daf0c 100644 (file)
 #include <glib.h>
 #include <string.h>
 
+#if HAVE_BOEHM_GC
+#include <gc/gc.h>
+#endif
+
 #include <mono/metadata/object.h>
 #include <mono/metadata/appdomain.h>
 #include <mono/metadata/assembly.h>
 
 static guint32 appdomain_thread_id = 0;
 
+static MonoJitInfoTable *
+mono_jit_info_table_new ()
+{
+       return g_array_new (FALSE, FALSE, sizeof (gpointer));
+}
+
+static void
+mono_jit_info_table_free (MonoJitInfoTable *table)
+{
+       g_array_free (table, TRUE);
+}
+
+static int
+mono_jit_info_table_index (MonoJitInfoTable *table, gpointer addr)
+{
+       int left = 0, right = table->len;
+
+       while (left < right) {
+               int pos = (left + right) / 2;
+               MonoJitInfo *ji = g_array_index (table, gpointer, pos);
+               gpointer start = ji->code_start;
+               gpointer end = start + ji->code_size;
+
+               if (addr < start)
+                       right = pos;
+               else if (addr >= end) 
+                       left = pos + 1;
+               else
+                       return pos;
+       }
+
+       return left;
+}
+
+MonoJitInfo *
+mono_jit_info_table_find (MonoDomain *domain, gpointer addr)
+{
+       MonoJitInfoTable *table = domain->jit_info_table;
+       int left = 0, right = table->len;
+
+       while (left < right) {
+               int pos = (left + right) / 2;
+               MonoJitInfo *ji = g_array_index (table, gpointer, pos);
+               gpointer start = ji->code_start;
+               gpointer end = start + ji->code_size;
+
+               if (addr < start)
+                       right = pos;
+               else if (addr >= end) 
+                       left = pos + 1;
+               else
+                       return ji;
+       }
+
+       /* maybe irt is shared code, so we also search in the root domain */
+       if (domain != mono_root_domain)
+               return mono_jit_info_table_find (domain, addr);
+
+       return NULL;
+}
+
 void
-mono_appdomain_init (char *friendly_name)
+mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji)
+{
+       MonoJitInfoTable *table = domain->jit_info_table;
+       gpointer start = ji->code_start;
+       int pos = mono_jit_info_table_index (table, start);
+
+       g_array_insert_val (table, pos, ji);
+}
+
+static int
+ldstr_hash (const char* str)
+{
+       guint len, h;
+       const char *end;
+       len = mono_metadata_decode_blob_size (str, &str);
+       end = str + len;
+       h = *str;
+       /*
+        * FIXME: The distribution may not be so nice with lots of
+        * null chars in the string.
+        */
+       for (str += 1; str < end; str++)
+               h = (h << 5) - h + *str;
+       return h;
+}
+
+static gboolean
+ldstr_equal (const char *str1, const char *str2) {
+       int len, len2;
+       len = mono_metadata_decode_blob_size (str1, NULL);
+       len2 = mono_metadata_decode_blob_size (str2, NULL);
+       if (len != len2)
+               return 0;
+       return memcmp (str1, str2, len) == 0;
+}
+
+#if HAVE_BOEHM_GC
+static void
+domain_finalizer (void *obj, void *data) {
+       g_print ("domain finalized\n");
+}
+#endif
+
+static MonoDomain *
+mono_create_domain ()
+{
+       MonoDomain *domain;
+
+#if HAVE_BOEHM_GC
+       domain = GC_malloc (sizeof (MonoDomain));
+       GC_register_finalizer (domain, domain_finalizer, NULL, NULL, NULL);
+#else
+       domain = g_new0 (MonoDomain, 1);
+#endif
+       domain->domain = NULL;
+       domain->setup = NULL;
+       domain->friendly_name = NULL;
+
+       domain->mp = mono_mempool_new ();
+       domain->env = g_hash_table_new (g_str_hash, g_str_equal);
+       domain->assemblies = g_hash_table_new (g_str_hash, g_str_equal);
+       domain->class_vtable_hash = mono_g_hash_table_new (NULL, NULL);
+       domain->jit_code_hash = g_hash_table_new (NULL, NULL);
+       domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)ldstr_hash, (GCompareFunc)ldstr_equal);
+       domain->jit_info_table = mono_jit_info_table_new ();
+       return domain;
+}
+
+MonoDomain *mono_root_domain = NULL;
+
+/**
+ * mono_init:
+ * 
+ * Creates the initial application domain and initializes the mono_defaults
+ * structure.
+ *
+ * Returns: the initial domain.
+ */
+MonoDomain *
+mono_init (const char *filename)
 {
-       static gboolean initialized = FALSE;
+       static MonoDomain *domain = NULL;
        MonoAppDomainSetup *setup;
        MonoAppDomain *ad;
+       MonoAssembly *ass;
        MonoClass *class;
        MonoString *name;
+       enum MonoImageOpenStatus status = MONO_IMAGE_OK;
 
-       if (initialized)
-               return;
+       if (domain)
+               g_assert_not_reached ();
 
        appdomain_thread_id = TlsAlloc ();
 
+       domain = mono_create_domain ();
+       mono_root_domain = domain;
+
+       TlsSetValue (appdomain_thread_id, domain);
+
+       /* find the corlib */
+       ass = mono_assembly_open (CORLIB_NAME, NULL, &status);
+       if ((status != MONO_IMAGE_OK) || (ass == NULL)) {
+               switch (status){
+               case MONO_IMAGE_ERROR_ERRNO:
+                       g_print ("The assembly corlib.dll was not found or could not be loaded.\n");
+                       g_print ("It should have been installed in the `%s' directory.\n", MONO_ASSEMBLIES);
+                       break;
+               case MONO_IMAGE_IMAGE_INVALID:
+                       g_print ("The file %s/corlib.dll is an invalid CIL image\n", MONO_ASSEMBLIES);
+                       break;
+               case MONO_IMAGE_MISSING_ASSEMBLYREF:
+                       g_print ("Minning assembly reference in %s/corlib.dll\n", MONO_ASSEMBLIES);
+                       break;
+               case MONO_IMAGE_OK:
+                       /* to suppress compiler warning */
+               }
+               
+               exit (1);
+       }
+       mono_defaults.corlib = ass->image;
+
+       mono_defaults.object_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Object");
+       g_assert (mono_defaults.object_class != 0);
+
+       mono_defaults.void_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Void");
+       g_assert (mono_defaults.void_class != 0);
+
+       mono_defaults.boolean_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Boolean");
+       g_assert (mono_defaults.boolean_class != 0);
+
+       mono_defaults.byte_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Byte");
+       g_assert (mono_defaults.byte_class != 0);
+
+       mono_defaults.sbyte_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "SByte");
+       g_assert (mono_defaults.sbyte_class != 0);
+
+       mono_defaults.int16_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Int16");
+       g_assert (mono_defaults.int16_class != 0);
+
+       mono_defaults.uint16_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "UInt16");
+       g_assert (mono_defaults.uint16_class != 0);
+
+       mono_defaults.int32_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Int32");
+       g_assert (mono_defaults.int32_class != 0);
+
+       mono_defaults.uint32_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "UInt32");
+       g_assert (mono_defaults.uint32_class != 0);
+
+       mono_defaults.uint_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "UIntPtr");
+       g_assert (mono_defaults.uint_class != 0);
+
+       mono_defaults.int_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "IntPtr");
+       g_assert (mono_defaults.int_class != 0);
+
+       mono_defaults.int64_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Int64");
+       g_assert (mono_defaults.int64_class != 0);
+
+       mono_defaults.uint64_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "UInt64");
+       g_assert (mono_defaults.uint64_class != 0);
+
+       mono_defaults.single_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Single");
+       g_assert (mono_defaults.single_class != 0);
+
+       mono_defaults.double_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Double");
+       g_assert (mono_defaults.double_class != 0);
+
+       mono_defaults.char_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Char");
+       g_assert (mono_defaults.char_class != 0);
+
+       mono_defaults.string_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "String");
+       g_assert (mono_defaults.string_class != 0);
+
+       mono_defaults.enum_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Enum");
+       g_assert (mono_defaults.enum_class != 0);
+
+       mono_defaults.array_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Array");
+       g_assert (mono_defaults.array_class != 0);
+
+       mono_defaults.multicastdelegate_class = mono_class_from_name (
+               mono_defaults.corlib, "System", "MulticastDelegate");
+       g_assert (mono_defaults.multicastdelegate_class != 0 );
+
+       mono_defaults.asyncresult_class = mono_class_from_name (
+               mono_defaults.corlib, "System.Runtime.Remoting.Messaging", 
+               "AsyncResult");
+       g_assert (mono_defaults.asyncresult_class != 0 );
+
+       mono_defaults.waithandle_class = mono_class_from_name (
+               mono_defaults.corlib, "System.Threading", "WaitHandle");
+       g_assert (mono_defaults.waithandle_class != 0 );
+
+       mono_defaults.typehandle_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "RuntimeTypeHandle");
+       g_assert (mono_defaults.typehandle_class != 0);
+
+       mono_defaults.methodhandle_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "RuntimeMethodHandle");
+       g_assert (mono_defaults.methodhandle_class != 0);
+
+       mono_defaults.fieldhandle_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "RuntimeFieldHandle");
+       g_assert (mono_defaults.fieldhandle_class != 0);
+
+       mono_defaults.monotype_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "MonoType");
+       g_assert (mono_defaults.monotype_class != 0);
+
+       mono_defaults.exception_class = mono_class_from_name (
+                mono_defaults.corlib, "System", "Exception");
+       g_assert (mono_defaults.exception_class != 0);
+
+       mono_defaults.thread_class = mono_class_from_name (
+                mono_defaults.corlib, "System.Threading", "Thread");
+       g_assert (mono_defaults.thread_class != 0);
+
        class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomainSetup");
-       setup = (MonoAppDomainSetup *) mono_object_new (class);
+       setup = (MonoAppDomainSetup *) mono_object_new (domain, class);
        ves_icall_System_AppDomainSetup_InitAppDomainSetup (setup);
 
-       name = mono_string_new (friendly_name);
-       ad = ves_icall_System_AppDomain_createDomain (name, setup);
+       name = mono_string_new (domain, g_path_get_basename (filename));
+
+       class = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
+       ad = (MonoAppDomain *) mono_object_new (domain, class);
+       ad->data = domain;
+       domain->domain = ad;
+       domain->setup = setup;
+       domain->friendly_name = name;
 
-       TlsSetValue (appdomain_thread_id, ad->data);
+       return domain;
 }
 
 void
@@ -49,19 +341,73 @@ ves_icall_System_AppDomainSetup_InitAppDomainSetup (MonoAppDomainSetup *setup)
        // fixme: implement me
 }
 
+/**
+ * mono_domain_transfer_object:
+ * @src: the source domain
+ * @dst: the destination domain
+ * @obj: the object to transfer
+ *
+ * This function is used to transfer objects between domains. This is done by
+ * marshalling or serialisation. 
+ */
 static MonoObject *
-mono_appdomain_transfer_object (MonoAppDomainData *src, MonoAppDomainData *dst, MonoObject *obj)
+mono_domain_transfer_object (MonoDomain *src, MonoDomain *dst, MonoObject *obj)
 {
+       MonoClass *klass;
+       MonoObject *res;        
+
+       if (!obj)
+               return NULL;
+
+       g_assert (obj->vtable->domain == src);
+
        /* fixme: transfer an object from one domain into another */
-       g_assert_not_reached ();
-       return obj;
+
+       klass = obj->vtable->klass;
+
+       if (MONO_CLASS_IS_ARRAY (klass)) {
+               MonoArray *ao = (MonoArray *)obj;
+               int esize, ecount, i;
+               guint32 *sizes;
+               
+               sizes = alloca (klass->rank * sizeof(guint32) * 2);
+               esize = mono_array_element_size (klass);
+               ecount = 1;
+               for (i = 0; i < klass->rank; ++i) {
+                       sizes [i] = ao->bounds [i].length;
+                       ecount *= ao->bounds [i].length;
+                       sizes [i + klass->rank] = ao->bounds [i].lower_bound;
+               }
+               res = (MonoObject *)mono_array_new_full (dst, klass, sizes, sizes + klass->rank);
+               if (klass->element_class->valuetype) {
+                       memcpy (res, (char *)ao + sizeof(MonoArray), esize * ecount);
+               } else {
+                       g_assert (esize == sizeof (gpointer));
+                       for (i = 0; i < ecount; i++) {
+                               int offset = sizeof (MonoArray) + esize * i;
+                               gpointer *src_ea = (gpointer *)((char *)ao + offset);
+                               gpointer *dst_ea = (gpointer *)((char *)res + offset);
+
+                               *dst_ea = mono_domain_transfer_object (src, dst, *src_ea);
+                       }
+               }
+       } else if (klass == mono_defaults.string_class) {
+               MonoString *str = (MonoString *)obj;
+               res = (MonoObject *)mono_string_new_utf16 (dst, 
+                       (const guint16 *)str->c_str->vector, str->length); 
+       } else {
+               // fixme: we need generic marshalling code here */
+               g_assert_not_reached ();
+       }
+       
+       return res;
 }
 
 MonoObject *
 ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
 {
-       MonoAppDomainData *add = ad->data;
-       MonoAppDomainData *cur = mono_appdomain_get ();
+       MonoDomain *add = ad->data;
+       MonoDomain *cur = mono_domain_get ();
        MonoObject *o;
        char *str;
 
@@ -96,21 +442,21 @@ ves_icall_System_AppDomain_GetData (MonoAppDomain *ad, MonoString *name)
        if (!o)
                return NULL;
 
-       return mono_appdomain_transfer_object (add, cur, o);
+       return mono_domain_transfer_object (add, cur, o);
 }
 
 void
 ves_icall_System_AppDomain_SetData (MonoAppDomain *ad, MonoString *name, MonoObject *data)
 {
-       MonoAppDomainData *add = ad->data;
-       MonoAppDomainData *cur = mono_appdomain_get ();
+       MonoDomain *add = ad->data;
+       MonoDomain *cur = mono_domain_get ();
        MonoObject *o;
        char *str;
 
        g_assert (ad != NULL);
        g_assert (name != NULL);
 
-       o = mono_appdomain_transfer_object (cur, add, data);
+       o = mono_domain_transfer_object (cur, add, data);
 
        /* fixme: need a hash func for MonoString */
        str = mono_string_to_utf8 (name);
@@ -136,14 +482,25 @@ ves_icall_System_AppDomain_getFriendlyName (MonoAppDomain *ad)
        return ad->data->friendly_name;
 }
 
-inline MonoAppDomainData *
-mono_appdomain_get ()
+/**
+ * mono_domain_get:
+ *
+ * Returns the current domain.
+ */
+inline MonoDomain *
+mono_domain_get ()
 {
-       return ((MonoAppDomainData *)TlsGetValue (appdomain_thread_id));
+       return ((MonoDomain *)TlsGetValue (appdomain_thread_id));
 }
 
+/**
+ * mono_domain_set:
+ * @domain: the new domain
+ *
+ * Sets the current domain to @domain.
+ */
 inline void
-mono_appdomain_set (MonoAppDomainData *domain)
+mono_domain_set (MonoDomain *domain)
 {
        TlsSetValue (appdomain_thread_id, domain);
 }
@@ -151,29 +508,27 @@ mono_appdomain_set (MonoAppDomainData *domain)
 MonoAppDomain *
 ves_icall_System_AppDomain_getCurDomain ()
 {
-       MonoAppDomainData *add = mono_appdomain_get ();
+       MonoDomain *add = mono_domain_get ();
        return add->domain;
 }
 
 MonoAppDomain *
 ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomainSetup *setup)
 {
+       MonoDomain *domain = mono_domain_get (); 
        MonoClass *adclass;
        MonoAppDomain *ad;
-       MonoAppDomainData *data;
+       MonoDomain *data;
        
        adclass = mono_class_from_name (mono_defaults.corlib, "System", "AppDomain");
        
        // fixme: pin all those objects
-       ad = (MonoAppDomain *) mono_object_new (adclass);
-       ad->data = data = g_new0 (MonoAppDomainData, 1);
+       ad = (MonoAppDomain *) mono_object_new (domain, adclass);
+       ad->data = data = mono_create_domain ();
        data->domain = ad;
        data->setup = setup;
        data->friendly_name = friendly_name;
 
-       data->env = g_hash_table_new (g_str_hash, g_str_equal);
-       data->assemblies = g_hash_table_new (g_str_hash, g_str_equal);
-
        // fixme: what to do next ?
 
        return ad;
@@ -181,6 +536,7 @@ ves_icall_System_AppDomain_createDomain (MonoString *friendly_name, MonoAppDomai
 
 typedef struct {
        MonoArray *res;
+       MonoDomain *domain;
        int idx;
 } add_assembly_helper_t;
 
@@ -189,18 +545,14 @@ add_assembly (gpointer key, gpointer value, gpointer user_data)
 {
        add_assembly_helper_t *ah = (add_assembly_helper_t *) user_data;
 
-       mono_array_set (ah->res, gpointer, ah->idx++, mono_assembly_get_object (value));
+       mono_array_set (ah->res, gpointer, ah->idx++, mono_assembly_get_object (ah->domain, value));
 }
 
-//
-// This is not correct, because we return all the assemblies loaded, and not
-// those that come from the AppDomain, but its better than nothing.
-//
 MonoArray *
 ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad)
 {
+       MonoDomain *domain = ad->data; 
        static MonoClass *System_Reflection_Assembly;
-       GHashTable *assemblies = mono_get_assemblies ();
        MonoArray *res;
        add_assembly_helper_t ah;
        
@@ -208,11 +560,12 @@ ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad)
                System_Reflection_Assembly = mono_class_from_name (
                        mono_defaults.corlib, "System.Reflection", "Assembly");
 
-       res = mono_array_new (System_Reflection_Assembly, g_hash_table_size (assemblies));
+       res = mono_array_new (domain, System_Reflection_Assembly, g_hash_table_size (domain->assemblies));
 
+       ah.domain = domain;
        ah.res = res;
        ah.idx = 0;
-       g_hash_table_foreach (assemblies, add_assembly, &ah);
+       g_hash_table_foreach (domain->assemblies, add_assembly, &ah);
 
        return res;
 }
@@ -221,6 +574,7 @@ ves_icall_System_AppDomain_GetAssemblies (MonoAppDomain *ad)
 MonoReflectionAssembly *
 ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoReflectionAssemblyName *assRef, MonoObject *evidence)
 {
+       MonoDomain *domain = ad->data; 
        char *name, *filename;
        enum MonoImageOpenStatus status = MONO_IMAGE_OK;
        MonoAssembly *ass;
@@ -242,31 +596,96 @@ ves_icall_System_AppDomain_LoadAssembly (MonoAppDomain *ad,  MonoReflectionAssem
        g_free (name);
 
        if (!ass)
-               mono_raise_exception ((MonoException *)mono_exception_from_name (
-                       mono_defaults.corlib, "System.IO", "FileNotFoundException"));
+               mono_raise_exception ((MonoException *)mono_exception_from_name (mono_defaults.corlib, "System.IO", "FileNotFoundException"));
 
-       return mono_assembly_get_object (ass);
+       return mono_assembly_get_object (domain, ass);
 }
 
 void
 ves_icall_System_AppDomain_Unload (MonoAppDomain *ad)
 {
-       g_warning ("AppDomain_Unload not implemented");
+       mono_domain_unload (ad->data, FALSE);
+}
+
+/**
+ * mono_domain_assembly_open:
+ * @domain: the application domain
+ * @name: file name of the assembly
+ *
+ * fixme: maybe we should integrate this with mono_assembly_open ??
+ */
+MonoAssembly *
+mono_domain_assembly_open (MonoDomain *domain, char *name)
+{
+       MonoAssembly *ass, *tmp;
+       int i;
+
+       if ((ass = g_hash_table_lookup (domain->assemblies, name)))
+               return ass;
+
+       if (!(ass = mono_assembly_open (name, NULL, NULL)))
+               return NULL;
+
+       g_hash_table_insert (domain->assemblies, ass->name, ass);
+
+       // fixme: maybe this must be recursive ?
+       for (i = 0; (tmp = ass->image->references [i]) != NULL; i++) {
+               if (!g_hash_table_lookup (domain->assemblies, tmp->name))
+                       g_hash_table_insert (domain->assemblies, tmp->name, tmp);
+       }
+
+       return ass;
+}
+
+static void
+remove_assembly (gpointer key, gpointer value, gpointer user_data)
+{
+       mono_assembly_close ((MonoAssembly *)value);
+}
+
+void
+mono_domain_unload (MonoDomain *domain, gboolean force)
+{
+       if ((domain == mono_root_domain) && !force) {
+               g_warning ("cant unload root domain");
+               return;
+       }
+
+       g_hash_table_foreach (domain->assemblies, remove_assembly, NULL);
+
+       g_hash_table_destroy (domain->env);
+       g_hash_table_destroy (domain->assemblies);
+       mono_g_hash_table_destroy (domain->class_vtable_hash);
+       g_hash_table_destroy (domain->jit_code_hash);
+       mono_g_hash_table_destroy (domain->ldstr_table);
+       mono_jit_info_table_free (domain->jit_info_table);
+       mono_mempool_destroy (domain->mp);
+       
+       // fixme: anything else required ? */
+
+#if HAVE_BOEHM_GC
+#else
+       g_free (domain);
+#endif
+
+       if ((domain == mono_root_domain))
+               mono_root_domain = NULL;
 }
 
 gint32
 ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file, 
                                            MonoObject *evidence, MonoArray *args)
 {
-       MonoAppDomainData *cdom = mono_appdomain_get ();
+       MonoDomain *cdom = mono_domain_get ();
        MonoAssembly *assembly;
        MonoImage *image;
        MonoCLIImageInfo *iinfo;
        MonoMethod *method;
+       MonoObject *margs;
        char *filename;
        gint32 res;
 
-       mono_appdomain_set (ad->data);
+       mono_domain_set (ad->data);
 
        filename = mono_string_to_utf8 (file);
        assembly = mono_assembly_open (filename, NULL, NULL);
@@ -274,7 +693,7 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file,
 
        if (!assembly) {
                mono_raise_exception ((MonoException *)mono_exception_from_name (
-                         mono_defaults.corlib, "System.IO", "FileNotFoundException"));
+                       mono_defaults.corlib, "System.IO", "FileNotFoundException"));
        }
 
        image = assembly->image;
@@ -284,9 +703,11 @@ ves_icall_System_AppDomain_ExecuteAssembly (MonoAppDomain *ad, MonoString *file,
        if (!method)
                g_error ("No entry point method found in %s", image->name);
 
-       res = mono_runtime_exec_main (method, args);
+       margs = mono_domain_transfer_object (cdom, ad->data, (MonoObject *)args);
+       res = mono_runtime_exec_main (method, (MonoArray *)margs);
 
-       mono_appdomain_set (cdom);
+       mono_domain_set (cdom);
 
        return res;
 }
+