[runtime] Add functionality for AOTing assemblies on demand when they are first used...
[mono.git] / mono / metadata / domain.c
index 1824c5ba8bd212c8bb2db39d35a1206b5245a6ac..b1b912f4e9bf501d4de270ccddde431bc4d0ad3f 100644 (file)
@@ -43,7 +43,7 @@
 #include <metadata/profiler-private.h>
 #include <mono/metadata/coree.h>
 
-#define DEBUG_DOMAIN_UNLOAD 1
+//#define DEBUG_DOMAIN_UNLOAD 1
 
 /* we need to use both the Tls* functions and __thread because
  * some archs may generate faster jit code with one meachanism
@@ -89,12 +89,13 @@ static guint16 appdomain_list_size = 0;
 static guint16 appdomain_next = 0;
 static MonoDomain **appdomains_list = NULL;
 static MonoImage *exe_image;
+static gboolean debug_domain_unload;
 
 gboolean mono_dont_free_domains;
 
-#define mono_appdomains_lock() EnterCriticalSection (&appdomains_mutex)
-#define mono_appdomains_unlock() LeaveCriticalSection (&appdomains_mutex)
-static CRITICAL_SECTION appdomains_mutex;
+#define mono_appdomains_lock() mono_mutex_lock (&appdomains_mutex)
+#define mono_appdomains_unlock() mono_mutex_unlock (&appdomains_mutex)
+static mono_mutex_t appdomains_mutex;
 
 static MonoDomain *mono_root_domain = NULL;
 
@@ -125,6 +126,7 @@ static const MonoRuntimeInfo supported_runtimes[] = {
        {"v4.0.30319","4.5", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
        {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
        {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, {4,0,0,0}, {4,0,0,0} } },
+       {"mobile",    "2.1", { {2,0,5,0}, {10,0,0,0}, {2,0,5,0}, {2,0,5,0} } },
        {"moonlight", "2.1", { {2,0,5,0}, { 9,0,0,0}, {3,5,0,0}, {3,0,0,0} } },
 };
 
@@ -136,6 +138,9 @@ static const MonoRuntimeInfo supported_runtimes[] = {
 static MonoCreateDomainFunc create_domain_hook;
 static MonoFreeDomainFunc free_domain_hook;
 
+/* AOT cache configuration */
+static MonoAotCacheConfig aot_cache_config;
+
 /* This is intentionally not in the header file, so people don't misuse it. */
 extern void _mono_debug_init_corlib (MonoDomain *domain);
 
@@ -854,13 +859,13 @@ mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
 {
        MonoJitInfo *ji;
 
-       mono_appdomains_lock ();
+       g_assert (mono_root_domain);
+       mono_domain_lock (mono_root_domain);
 
        /*
         * We reuse MonoJitInfoTable to store AOT module info,
         * this gives us async-safe lookup.
         */
-       g_assert (mono_root_domain);
        if (!mono_root_domain->aot_modules) {
                mono_root_domain->num_jit_info_tables ++;
                mono_root_domain->aot_modules = jit_info_table_new (mono_root_domain);
@@ -872,7 +877,7 @@ mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end)
        ji->code_size = (guint8*)end - (guint8*)start;
        jit_info_table_add (mono_root_domain, &mono_root_domain->aot_modules, ji);
 
-       mono_appdomains_unlock ();
+       mono_domain_unlock (mono_root_domain);
 }
 
 void
@@ -983,6 +988,16 @@ mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji)
        }
 }
 
+static int
+try_block_hole_table_size (MonoJitInfo *ji)
+{
+       MonoTryBlockHoleTableJitInfo *table;
+
+       table = mono_jit_info_get_try_block_hole_table_info (ji);
+       g_assert (table);
+       return sizeof (MonoTryBlockHoleTableJitInfo) + table->num_holes * sizeof (MonoTryBlockHoleJitInfo);
+}
+
 MonoArchEHJitInfo*
 mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
 {
@@ -991,7 +1006,7 @@ mono_jit_info_get_arch_eh_info (MonoJitInfo *ji)
                if (ji->has_generic_jit_info)
                        ptr += sizeof (MonoGenericJitInfo);
                if (ji->has_try_block_holes)
-                       ptr += sizeof (MonoTryBlockHoleTableJitInfo);
+                       ptr += try_block_hole_table_size (ji);
                return (MonoArchEHJitInfo*)ptr;
        } else {
                return NULL;
@@ -1006,7 +1021,7 @@ mono_jit_info_get_cas_info (MonoJitInfo *ji)
                if (ji->has_generic_jit_info)
                        ptr += sizeof (MonoGenericJitInfo);
                if (ji->has_try_block_holes)
-                       ptr += sizeof (MonoTryBlockHoleTableJitInfo);
+                       ptr += try_block_hole_table_size (ji);
                if (ji->has_arch_eh_info)
                        ptr += sizeof (MonoArchEHJitInfo);
                return (MonoMethodCasInfo*)ptr;
@@ -1035,6 +1050,7 @@ lock_free_mempool_free (LockFreeMempool *mp)
                mono_vfree (chunk, mono_pagesize ());
                chunk = next;
        }
+       g_free (mp);
 }
 
 /*
@@ -1291,10 +1307,10 @@ mono_domain_create (void)
        domain->finalizable_objects_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        domain->ftnptrs_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
 
-       InitializeCriticalSection (&domain->lock);
-       InitializeCriticalSection (&domain->assemblies_lock);
-       InitializeCriticalSection (&domain->jit_code_hash_lock);
-       InitializeCriticalSection (&domain->finalizable_objects_hash_lock);
+       mono_mutex_init_recursive (&domain->lock);
+       mono_mutex_init_recursive (&domain->assemblies_lock);
+       mono_mutex_init_recursive (&domain->jit_code_hash_lock);
+       mono_mutex_init_recursive (&domain->finalizable_objects_hash_lock);
 
        domain->method_rgctx_hash = NULL;
 
@@ -1339,6 +1355,10 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
        const MonoRuntimeInfo* runtimes [G_N_ELEMENTS (supported_runtimes) + 1];
        int n;
 
+#ifdef DEBUG_DOMAIN_UNLOAD
+       debug_domain_unload = TRUE;
+#endif
+
        if (domain)
                g_assert_not_reached ();
 
@@ -1364,7 +1384,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char *
        MONO_FAST_TLS_INIT (tls_appdomain);
        mono_native_tls_alloc (&appdomain_thread_id, NULL);
 
-       InitializeCriticalSection (&appdomains_mutex);
+       mono_mutex_init_recursive (&appdomains_mutex);
 
        mono_metadata_init ();
        mono_images_init ();
@@ -1772,7 +1792,7 @@ mono_cleanup (void)
        mono_metadata_cleanup ();
 
        mono_native_tls_free (appdomain_thread_id);
-       DeleteCriticalSection (&appdomains_mutex);
+       mono_mutex_destroy (&appdomains_mutex);
 
 #ifndef HOST_WIN32
        wapi_cleanup ();
@@ -1975,6 +1995,13 @@ mono_domain_free (MonoDomain *domain, gboolean force)
 
        mono_reflection_cleanup_domain (domain);
 
+       /* This must be done before type_hash is freed */
+       if (domain->class_vtable_array) {
+               int i;
+               for (i = 0; i < domain->class_vtable_array->len; ++i)
+                       unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
+       }
+
        if (domain->type_hash) {
                mono_g_hash_table_destroy (domain->type_hash);
                domain->type_hash = NULL;
@@ -1984,12 +2011,6 @@ mono_domain_free (MonoDomain *domain, gboolean force)
                domain->type_init_exception_hash = NULL;
        }
 
-       if (domain->class_vtable_array) {
-               int i;
-               for (i = 0; i < domain->class_vtable_array->len; ++i)
-                       unregister_vtable_reflection_type (g_ptr_array_index (domain->class_vtable_array, i));
-       }
-
        for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
                MonoAssembly *ass = tmp->data;
                mono_assembly_release_gc_roots (ass);
@@ -2005,7 +2026,7 @@ mono_domain_free (MonoDomain *domain, gboolean force)
        /* Close dynamic assemblies first, since they have no ref count */
        for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) {
                MonoAssembly *ass = tmp->data;
-               if (!ass->image || !ass->image->dynamic)
+               if (!ass->image || !image_is_dynamic (ass->image))
                        continue;
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
                if (!mono_assembly_close_except_image_pools (ass))
@@ -2016,7 +2037,7 @@ mono_domain_free (MonoDomain *domain, gboolean force)
                MonoAssembly *ass = tmp->data;
                if (!ass)
                        continue;
-               if (!ass->image || ass->image->dynamic)
+               if (!ass->image || image_is_dynamic (ass->image))
                        continue;
                mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count);
                if (!mono_assembly_close_except_image_pools (ass))
@@ -2085,18 +2106,18 @@ mono_domain_free (MonoDomain *domain, gboolean force)
        max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc);
        max_domain_code_size = MAX (max_domain_code_size, code_size);
 
-#ifdef DEBUG_DOMAIN_UNLOAD
-       mono_mempool_invalidate (domain->mp);
-       mono_code_manager_invalidate (domain->code_mp);
-#else
+       if (debug_domain_unload) {
+               mono_mempool_invalidate (domain->mp);
+               mono_code_manager_invalidate (domain->code_mp);
+       } else {
 #ifndef DISABLE_PERFCOUNTERS
-       mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
+               mono_perfcounters->loader_bytes -= mono_mempool_get_allocated (domain->mp);
 #endif
-       mono_mempool_destroy (domain->mp);
-       domain->mp = NULL;
-       mono_code_manager_destroy (domain->code_mp);
-       domain->code_mp = NULL;
-#endif 
+               mono_mempool_destroy (domain->mp);
+               domain->mp = NULL;
+               mono_code_manager_destroy (domain->code_mp);
+               domain->code_mp = NULL;
+       }
        lock_free_mempool_free (domain->lock_free_mp);
        domain->lock_free_mp = NULL;
 
@@ -2119,10 +2140,10 @@ mono_domain_free (MonoDomain *domain, gboolean force)
                domain->ftnptrs_hash = NULL;
        }
 
-       DeleteCriticalSection (&domain->finalizable_objects_hash_lock);
-       DeleteCriticalSection (&domain->assemblies_lock);
-       DeleteCriticalSection (&domain->jit_code_hash_lock);
-       DeleteCriticalSection (&domain->lock);
+       mono_mutex_destroy (&domain->finalizable_objects_hash_lock);
+       mono_mutex_destroy (&domain->assemblies_lock);
+       mono_mutex_destroy (&domain->jit_code_hash_lock);
+       mono_mutex_destroy (&domain->lock);
        domain->setup = NULL;
 
        mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED));
@@ -2752,3 +2773,15 @@ mono_framework_version (void)
 {
        return current_runtime->framework_version [0] - '0';
 }
+
+void
+mono_enable_debug_domain_unload (gboolean enable)
+{
+       debug_domain_unload = enable;
+}
+
+MonoAotCacheConfig *
+mono_get_aot_cache_config (void)
+{
+       return &aot_cache_config;
+}