2009-06-04 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / domain.c
index 9da93c33049c7795e514c2a0ed394ef9ea7afa88..f870683f131136693a4a31e3fb2ff8474bc35478 100644 (file)
@@ -1199,6 +1199,9 @@ mono_domain_create (void)
        domain->jit_info_table = jit_info_table_new (domain);
        domain->jit_info_free_queue = NULL;
        domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+#ifndef HAVE_SGEN_GC
+       domain->track_resurrection_handles_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
+#endif
 
        InitializeCriticalSection (&domain->lock);
        InitializeCriticalSection (&domain->assemblies_lock);
@@ -1562,6 +1565,9 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
        mono_defaults.internals_visible_class = mono_class_from_name (
                mono_defaults.corlib, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
 
+       mono_defaults.critical_finalizer_object = mono_class_from_name (
+               mono_defaults.corlib, "System.Runtime.ConstrainedExecution", "CriticalFinalizerObject");
+
        /*
         * mscorlib needs a little help, only now it can load its friends list (after we have
         * loaded the InternalsVisibleToAttribute), load it now
@@ -1750,6 +1756,28 @@ mono_domain_get ()
        return GET_APPDOMAIN ();
 }
 
+void
+mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception)
+{
+       MonoThread *thread;
+
+       if (mono_domain_get () == domain)
+               return;
+
+       SET_APPDOMAIN (domain);
+       SET_APPCONTEXT (domain->default_context);
+
+       if (migrate_exception) {
+               thread = mono_thread_current ();
+               if (!thread->abort_exc)
+                       return;
+
+               g_assert (thread->abort_exc->object.vtable->domain != domain);
+               MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
+               g_assert (thread->abort_exc->object.vtable->domain == domain);
+       }
+}
+
 /**
  * mono_domain_set_internal:
  * @domain: the new domain
@@ -1759,8 +1787,7 @@ mono_domain_get ()
 void
 mono_domain_set_internal (MonoDomain *domain)
 {
-       SET_APPDOMAIN (domain);
-       SET_APPCONTEXT (domain->default_context);
+       mono_domain_set_internal_with_options (domain, TRUE);
 }
 
 void
@@ -1817,6 +1844,12 @@ mono_domain_assembly_open (MonoDomain *domain, const char *name)
        return ass;
 }
 
+static void
+free_slist (gpointer key, gpointer value, gpointer user_data)
+{
+       g_slist_free (value);
+}
+
 void
 mono_domain_free (MonoDomain *domain, gboolean force)
 {
@@ -1837,6 +1870,8 @@ mono_domain_free (MonoDomain *domain, gboolean force)
 
        mono_debug_domain_unload (domain);
 
+       mono_gc_clear_domain (domain);
+
        mono_appdomains_lock ();
        appdomains_list [domain->domain_id] = NULL;
        mono_appdomains_unlock ();
@@ -1910,20 +1945,27 @@ mono_domain_free (MonoDomain *domain, gboolean force)
        mono_code_manager_destroy (domain->code_mp);
        domain->code_mp = NULL;
 #endif 
+
+       mono_reflection_cleanup_domain (domain);
+       
        if (domain->type_hash) {
                mono_g_hash_table_destroy (domain->type_hash);
                domain->type_hash = NULL;
        }
-       if (domain->refobject_hash) {
-               mono_g_hash_table_destroy (domain->refobject_hash);
-               domain->refobject_hash = NULL;
-       }
        if (domain->type_init_exception_hash) {
                mono_g_hash_table_destroy (domain->type_init_exception_hash);
                domain->type_init_exception_hash = NULL;
        }
        g_hash_table_destroy (domain->finalizable_objects_hash);
        domain->finalizable_objects_hash = NULL;
+#ifndef HAVE_SGEN_GC
+       if (domain->track_resurrection_objects_hash) {
+               g_hash_table_foreach (domain->track_resurrection_objects_hash, free_slist, NULL);
+               g_hash_table_destroy (domain->track_resurrection_objects_hash);
+       }
+       if (domain->track_resurrection_handles_hash)
+               g_hash_table_destroy (domain->track_resurrection_handles_hash);
+#endif
        if (domain->method_rgctx_hash) {
                g_hash_table_destroy (domain->method_rgctx_hash);
                domain->method_rgctx_hash = NULL;