X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fdomain.c;h=ab57fee5322e70fb164fc8106865db4d4ef95ff2;hb=c5c194098baf1d1478473bf3097c85288281c2f7;hp=6d9f4b14f65cb15d32a965025daeff14126158c7;hpb=3331634f37c395ea87d15a2f3338b2bc66a8470a;p=mono.git diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index 6d9f4b14f65..ab57fee5322 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -5,7 +5,8 @@ * Dietmar Maurer (dietmar@ximian.com) * Patrik Torstensson * - * (C) 2001 Ximian, Inc. + * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com) + * Copyright 2004-2009 Novell, Inc (http://www.novell.com) */ #include @@ -16,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -43,24 +44,41 @@ * but we can't depend on this). */ static guint32 appdomain_thread_id = -1; - -#ifdef HAVE_KW_THREAD -static __thread MonoDomain * tls_appdomain MONO_TLS_FAST; -#define GET_APPDOMAIN() tls_appdomain + +/* + * Avoid calling TlsSetValue () if possible, since in the io-layer, it acquires + * a global lock (!) so it is a contention point. + */ +#if (defined(__i386__) || defined(__x86_64__)) && !defined(HOST_WIN32) +#define NO_TLS_SET_VALUE +#endif + +#ifdef MONO_HAVE_FAST_TLS + +MONO_FAST_TLS_DECLARE(tls_appdomain); + +#define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain)) + +#ifdef NO_TLS_SET_VALUE #define SET_APPDOMAIN(x) do { \ - tls_appdomain = x; \ + MONO_FAST_TLS_SET (tls_appdomain,x); \ +} while (FALSE) +#else +#define SET_APPDOMAIN(x) do { \ + MONO_FAST_TLS_SET (tls_appdomain,x); \ TlsSetValue (appdomain_thread_id, x); \ } while (FALSE) +#endif -#else +#else /* !MONO_HAVE_FAST_TLS */ #define GET_APPDOMAIN() ((MonoDomain *)TlsGetValue (appdomain_thread_id)) #define SET_APPDOMAIN(x) TlsSetValue (appdomain_thread_id, x); #endif -#define GET_APPCONTEXT() (mono_thread_current ()->current_appcontext) -#define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_current (), current_appcontext, (x)) +#define GET_APPCONTEXT() (mono_thread_internal_current ()->current_appcontext) +#define SET_APPCONTEXT(x) MONO_OBJECT_SETREF (mono_thread_internal_current (), current_appcontext, (x)) static guint16 appdomain_list_size = 0; static guint16 appdomain_next = 0; @@ -110,16 +128,17 @@ static MonoAotModuleInfoTable *aot_modules = NULL; /* This is the list of runtime versions supported by this JIT. */ static const MonoRuntimeInfo supported_runtimes[] = { - {"v1.0.3705", "1.0", { {1,0,5000,0}, {7,0,5000,0} } }, - {"v1.1.4322", "1.0", { {1,0,5000,0}, {7,0,5000,0} } }, - {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0} } }, - {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0} } }, - {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0} } }, + {"v2.0.50215","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } }, + {"v2.0.50727","2.0", { {2,0,0,0}, {8,0,0,0}, { 3, 5, 0, 0 } } }, + {"v4.0.20506","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } }, + {"v4.0.30128","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } }, + {"v4.0.30319","4.0", { {4,0,0,0}, {10,0,0,0}, { 4, 0, 0, 0 } } }, + {"moonlight", "2.1", { {2,0,5,0}, {9,0,0,0}, { 3, 5, 0, 0 } } }, }; /* The stable runtime version */ -#define DEFAULT_RUNTIME_VERSION "v1.1.4322" +#define DEFAULT_RUNTIME_VERSION "v2.0.50727" /* Callbacks installed by the JIT */ static MonoCreateDomainFunc create_domain_hook; @@ -198,7 +217,7 @@ jit_info_table_new_chunk (void) static MonoJitInfoTable * jit_info_table_new (MonoDomain *domain) { - MonoJitInfoTable *table = g_malloc0 (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*)); + MonoJitInfoTable *table = g_malloc0 (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*)); table->domain = domain; table->num_chunks = 1; @@ -355,6 +374,7 @@ mono_jit_info_table_find (MonoDomain *domain, char *addr) MonoJitInfo *ji; int chunk_pos, pos; MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); + MonoImage *image; ++mono_stats.jit_info_table_lookup_count; @@ -409,20 +429,18 @@ mono_jit_info_table_find (MonoDomain *domain, char *addr) } while (chunk_pos < table->num_chunks); not_found: + if (!hp) + return NULL; + mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); - /* maybe it is shared code, so we also search in the root domain */ ji = NULL; - if (domain != mono_root_domain) - ji = mono_jit_info_table_find (mono_root_domain, addr); - - if (ji == NULL) { - /* Maybe its an AOT module */ - MonoImage *image = mono_jit_info_find_aot_module ((guint8*)addr); - if (image) - ji = jit_info_find_in_aot_func (domain, image, addr); - } + + /* Maybe its an AOT module */ + image = mono_jit_info_find_aot_module ((guint8*)addr); + if (image) + ji = jit_info_find_in_aot_func (domain, image, addr); return ji; } @@ -483,7 +501,7 @@ jit_info_table_realloc (MonoJitInfoTable *old) required_size = (int)((long)num_elements * JIT_INFO_TABLE_FILL_RATIO_DENOM / JIT_INFO_TABLE_FILL_RATIO_NOM); num_chunks = (required_size + MONO_JIT_INFO_TABLE_CHUNK_SIZE - 1) / MONO_JIT_INFO_TABLE_CHUNK_SIZE; - new = g_malloc (sizeof (MonoJitInfoTable) + sizeof (MonoJitInfoTableChunk*) * num_chunks); + new = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * num_chunks); new->domain = old->domain; new->num_chunks = num_chunks; @@ -552,7 +570,7 @@ jit_info_table_split_chunk (MonoJitInfoTableChunk *chunk, MonoJitInfoTableChunk static MonoJitInfoTable* jit_info_table_copy_and_split_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) { - MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable) + MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * (table->num_chunks + 1)); int i, j; @@ -600,7 +618,7 @@ jit_info_table_purify_chunk (MonoJitInfoTableChunk *old) static MonoJitInfoTable* jit_info_table_copy_and_purify_chunk (MonoJitInfoTable *table, MonoJitInfoTableChunk *chunk) { - MonoJitInfoTable *new_table = g_malloc (sizeof (MonoJitInfoTable) + MonoJitInfoTable *new_table = g_malloc (MONO_SIZEOF_JIT_INFO_TABLE + sizeof (MonoJitInfoTableChunk*) * table->num_chunks); int i, j; @@ -1001,7 +1019,19 @@ mono_jit_info_set_generic_sharing_context (MonoJitInfo *ji, MonoGenericSharingCo gi->generic_sharing_context = gsctx; } - + +MonoTryBlockHoleTableJitInfo* +mono_jit_info_get_try_block_hole_table_info (MonoJitInfo *ji) +{ + if (ji->has_try_block_holes) { + char *ptr = (char*)&ji->clauses [ji->num_clauses]; + if (ji->has_generic_jit_info) + ptr += sizeof (MonoGenericJitInfo); + return (MonoTryBlockHoleTableJitInfo*)ptr; + } else { + return NULL; + } +} void mono_install_create_domain_hook (MonoCreateDomainFunc func) { @@ -1129,7 +1159,7 @@ domain_id_alloc (MonoDomain *domain) return id; } -static guint32 domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1]; +static gsize domain_gc_bitmap [sizeof(MonoDomain)/4/32 + 1]; static gpointer domain_gc_desc = NULL; static guint32 domain_shadow_serial = 0L; @@ -1146,13 +1176,24 @@ mono_domain_create (void) unsigned int i, bit = 0; for (i = G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_OBJECT); i < G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED); i += sizeof (gpointer)) { bit = i / sizeof (gpointer); - domain_gc_bitmap [bit / 32] |= 1 << (bit % 32); + domain_gc_bitmap [bit / 32] |= (gsize) 1 << (bit % 32); } domain_gc_desc = mono_gc_make_descr_from_bitmap ((gsize*)domain_gc_bitmap, bit + 1); } mono_appdomains_unlock (); +#ifdef HAVE_BOEHM_GC + /* + * Boehm doesn't like roots inside GC allocated objects, and alloc_fixed returns + * a GC_MALLOC-ed object, contrary to the api docs. This causes random crashes when + * running the corlib test suite. + * To solve this, we pass a NULL descriptor, and don't register roots. + */ + domain = mono_gc_alloc_fixed (sizeof (MonoDomain), NULL); +#else domain = mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc); + mono_gc_register_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED), G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_LAST_GC_TRACKED) - G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED), NULL); +#endif domain->shadow_serial = shadow_serial; domain->domain = NULL; domain->setup = NULL; @@ -1165,21 +1206,24 @@ mono_domain_create (void) domain->code_mp = mono_code_manager_new (); domain->env = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC); domain->domain_assemblies = NULL; - domain->class_vtable_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); + domain->assembly_bindings = NULL; + domain->assembly_bindings_parsed = FALSE; + domain->class_vtable_array = g_ptr_array_new (); domain->proxy_vtable_hash = g_hash_table_new ((GHashFunc)mono_ptrarray_hash, (GCompareFunc)mono_ptrarray_equal); domain->static_data_array = NULL; mono_jit_code_hash_init (&domain->jit_code_hash); - domain->ldstr_table = mono_g_hash_table_new ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal); + domain->ldstr_table = mono_g_hash_table_new_type ((GHashFunc)mono_string_hash, (GCompareFunc)mono_string_equal, MONO_HASH_KEY_VALUE_GC); domain->num_jit_info_tables = 1; 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); + domain->track_resurrection_handles_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); - domain->shared_generics_hash = NULL; domain->method_rgctx_hash = NULL; mono_appdomains_lock (); @@ -1224,11 +1268,12 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * if (domain) g_assert_not_reached (); -#ifdef PLATFORM_WIN32 +#ifdef HOST_WIN32 /* Avoid system error message boxes. */ SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); - +#ifdef ENABLE_COREE mono_load_coree (exe_filename); +#endif #endif mono_perfcounters_init (); @@ -1239,6 +1284,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_gc_base_init (); + MONO_FAST_TLS_INIT (tls_appdomain); appdomain_thread_id = TlsAlloc (); InitializeCriticalSection (&appdomains_mutex); @@ -1251,7 +1297,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_reflection_init (); /* FIXME: When should we release this memory? */ - MONO_GC_REGISTER_ROOT (appdomains_list); + MONO_GC_REGISTER_ROOT_FIXED (appdomains_list); domain = mono_domain_create (); mono_root_domain = domain; @@ -1266,7 +1312,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * * exe_image, and close it during shutdown. */ get_runtimes_from_exe (exe_filename, &exe_image, runtimes); -#ifdef PLATFORM_WIN32 +#ifdef ENABLE_COREE if (!exe_image) { exe_image = mono_assembly_open_from_bundle (exe_filename, NULL, FALSE); if (!exe_image) @@ -1284,7 +1330,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * runtimes [0] = default_runtime; runtimes [1] = NULL; g_print ("WARNING: The runtime version supported by this application is unavailable.\n"); - g_print ("Using default runtime: %s\n", default_runtime->runtime_version); + g_print ("Using default runtime: %s\n", default_runtime->runtime_version); } /* The selected runtime will be the first one for which there is a mscrolib.dll */ @@ -1296,11 +1342,6 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * } - /* Now that we have a runtime, set the policy for unhandled exceptions */ - if (mono_framework_version () < 2) { - mono_runtime_unhandled_exception_policy_set (MONO_UNHANDLED_POLICY_LEGACY); - } - if ((status != MONO_IMAGE_OK) || (ass == NULL)) { switch (status){ case MONO_IMAGE_ERROR_ERRNO: { @@ -1416,9 +1457,9 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * "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.manualresetevent_class = mono_class_from_name ( + mono_defaults.corlib, "System.Threading", "ManualResetEvent"); + g_assert (mono_defaults.manualresetevent_class != 0 ); mono_defaults.typehandle_class = mono_class_from_name ( mono_defaults.corlib, "System", "RuntimeTypeHandle"); @@ -1452,6 +1493,16 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.corlib, "System.Threading", "Thread"); g_assert (mono_defaults.thread_class != 0); + mono_defaults.internal_thread_class = mono_class_from_name ( + mono_defaults.corlib, "System.Threading", "InternalThread"); + if (!mono_defaults.internal_thread_class) { + /* This can happen with an old mscorlib */ + fprintf (stderr, "Corlib too old for this runtime.\n"); + fprintf (stderr, "Loaded from: %s\n", + mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown"); + exit (1); + } + mono_defaults.appdomain_class = mono_class_from_name ( mono_defaults.corlib, "System", "AppDomain"); g_assert (mono_defaults.appdomain_class != 0); @@ -1537,6 +1588,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 @@ -1597,7 +1651,11 @@ mono_init (const char *domain_name) /** * mono_init_from_assembly: - * + * @domain_name: name to give to the initial domain + * @filename: filename to load on startup + * + * Used by the runtime, users should use mono_jit_init instead. + * * Creates the initial application domain and initializes the mono_defaults * structure. * This function is guaranteed to not run any IL code. @@ -1616,8 +1674,11 @@ mono_init_from_assembly (const char *domain_name, const char *filename) /** * mono_init_version: * + * Used by the runtime, users should use mono_jit_init instead. + * * Creates the initial application domain and initializes the mono_defaults * structure. + * * This function is guaranteed to not run any IL code. * The runtime is initialized using the provided rutime version. * @@ -1679,6 +1740,9 @@ mono_cleanup (void) { mono_close_exe_image (); + mono_defaults.corlib = NULL; + + mono_config_cleanup (); mono_loader_cleanup (); mono_classes_cleanup (); mono_assemblies_cleanup (); @@ -1688,6 +1752,14 @@ mono_cleanup (void) TlsFree (appdomain_thread_id); DeleteCriticalSection (&appdomains_mutex); + + /* + * This should be called last as TlsGetValue ()/TlsSetValue () can be called during + * shutdown. + */ +#ifndef HOST_WIN32 + _wapi_cleanup (); +#endif } void @@ -1725,6 +1797,34 @@ mono_domain_get () return GET_APPDOMAIN (); } +void +mono_domain_unset (void) +{ + SET_APPDOMAIN (NULL); +} + +void +mono_domain_set_internal_with_options (MonoDomain *domain, gboolean migrate_exception) +{ + MonoInternalThread *thread; + + if (mono_domain_get () == domain) + return; + + SET_APPDOMAIN (domain); + SET_APPCONTEXT (domain->default_context); + + if (migrate_exception) { + thread = mono_thread_internal_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 @@ -1734,8 +1834,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 @@ -1773,6 +1872,7 @@ mono_domain_foreach (MonoDomainFunc func, gpointer user_data) MonoAssembly * mono_domain_assembly_open (MonoDomain *domain, const char *name) { + MonoDomain *current; MonoAssembly *ass; GSList *tmp; @@ -1786,30 +1886,32 @@ mono_domain_assembly_open (MonoDomain *domain, const char *name) } mono_domain_assemblies_unlock (domain); - if (!(ass = mono_assembly_open (name, NULL))) - return NULL; + if (domain != mono_domain_get ()) { + current = mono_domain_get (); + + mono_domain_set (domain, FALSE); + ass = mono_assembly_open (name, NULL); + mono_domain_set (current, FALSE); + } else { + ass = mono_assembly_open (name, NULL); + } return ass; } -MonoJitInfo* -mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *method) +static void +free_slist (gpointer key, gpointer value, gpointer user_data) { - if (!domain->shared_generics_hash) - return NULL; - - return g_hash_table_lookup (domain->shared_generics_hash, method); + g_slist_free (value); } -void -mono_domain_register_shared_generic (MonoDomain *domain, MonoMethod *method, MonoJitInfo *jit_info) +static void +unregister_vtable_reflection_type (MonoVTable *vtable) { - if (!domain->shared_generics_hash) - domain->shared_generics_hash = g_hash_table_new (mono_aligned_addr_hash, NULL); - - g_assert (domain->shared_generics_hash); + MonoObject *type = vtable->type; - g_hash_table_insert (domain->shared_generics_hash, method, jit_info); + if (type->vtable->klass != mono_defaults.monotype_class) + MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type); } void @@ -1827,15 +1929,76 @@ mono_domain_free (MonoDomain *domain, gboolean force) mono_profiler_appdomain_event (domain, MONO_PROFILE_START_UNLOAD); - if (free_domain_hook) - free_domain_hook (domain); - mono_debug_domain_unload (domain); mono_appdomains_lock (); appdomains_list [domain->domain_id] = NULL; mono_appdomains_unlock (); + /* must do this early as it accesses fields and types */ + if (domain->special_static_fields) { + mono_alloc_special_static_data_free (domain->special_static_fields); + g_hash_table_destroy (domain->special_static_fields); + domain->special_static_fields = NULL; + } + + /* + * We must destroy all these hash tables here because they + * contain references to managed objects belonging to the + * domain. Once we let the GC clear the domain there must be + * no more such references, or we'll crash if a collection + * occurs. + */ + mono_g_hash_table_destroy (domain->ldstr_table); + domain->ldstr_table = NULL; + + mono_g_hash_table_destroy (domain->env); + domain->env = NULL; + + mono_reflection_cleanup_domain (domain); + + if (domain->type_hash) { + mono_g_hash_table_destroy (domain->type_hash); + domain->type_hash = NULL; + } + if (domain->type_init_exception_hash) { + mono_g_hash_table_destroy (domain->type_init_exception_hash); + 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)); + } + + /* This needs to be done before closing assemblies */ + mono_gc_clear_domain (domain); + + for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { + MonoAssembly *ass = tmp->data; + mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s[%p], assembly %s[%p], ref_count=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count); + if (!mono_assembly_close_except_image_pools (ass)) + tmp->data = NULL; + } + + for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { + MonoAssembly *ass = tmp->data; + if (ass) + mono_assembly_close_finish (ass); + } + g_slist_free (domain->domain_assemblies); + domain->domain_assemblies = NULL; + + /* + * Send this after the assemblies have been unloaded and the domain is still in a + * usable state. + */ + mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD); + + if (free_domain_hook) + free_domain_hook (domain); + /* FIXME: free delegate_hash_table when it's used */ if (domain->search_path) { g_strfreev (domain->search_path); @@ -1847,27 +2010,13 @@ mono_domain_free (MonoDomain *domain, gboolean force) domain->out_of_memory_ex = NULL; domain->null_reference_ex = NULL; domain->stack_overflow_ex = NULL; + domain->ephemeron_tombstone = NULL; domain->entry_assembly = NULL; - /* must do this early as it accesses fields and types */ - if (domain->special_static_fields) { - mono_alloc_special_static_data_free (domain->special_static_fields); - g_hash_table_destroy (domain->special_static_fields); - domain->special_static_fields = NULL; - } - for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { - MonoAssembly *ass = tmp->data; - mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Unloading domain %s %p, assembly %s %p, refcount=%d\n", domain->friendly_name, domain, ass->aname.name, ass, ass->ref_count); - mono_assembly_close (ass); - } - g_slist_free (domain->domain_assemblies); - domain->domain_assemblies = NULL; g_free (domain->friendly_name); domain->friendly_name = NULL; - mono_g_hash_table_destroy (domain->env); - domain->env = NULL; - g_hash_table_destroy (domain->class_vtable_hash); - domain->class_vtable_hash = NULL; + g_ptr_array_free (domain->class_vtable_array, TRUE); + domain->class_vtable_array = NULL; g_hash_table_destroy (domain->proxy_vtable_hash); domain->proxy_vtable_hash = NULL; if (domain->static_data_array) { @@ -1875,8 +2024,6 @@ mono_domain_free (MonoDomain *domain, gboolean force) domain->static_data_array = NULL; } mono_internal_hash_table_destroy (&domain->jit_code_hash); - mono_g_hash_table_destroy (domain->ldstr_table); - domain->ldstr_table = NULL; /* * There might still be jit info tables of this domain which @@ -1905,24 +2052,15 @@ mono_domain_free (MonoDomain *domain, gboolean force) mono_code_manager_destroy (domain->code_mp); domain->code_mp = NULL; #endif - 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; - if (domain->shared_generics_hash) { - g_hash_table_destroy (domain->shared_generics_hash); - domain->shared_generics_hash = NULL; + 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); if (domain->method_rgctx_hash) { g_hash_table_destroy (domain->method_rgctx_hash); domain->method_rgctx_hash = NULL; @@ -1932,14 +2070,15 @@ mono_domain_free (MonoDomain *domain, gboolean force) domain->generic_virtual_cases = NULL; } + DeleteCriticalSection (&domain->finalizable_objects_hash_lock); DeleteCriticalSection (&domain->assemblies_lock); DeleteCriticalSection (&domain->jit_code_hash_lock); DeleteCriticalSection (&domain->lock); domain->setup = NULL; - /* FIXME: anything else required ? */ + mono_gc_deregister_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED)); - mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD); + /* FIXME: anything else required ? */ mono_gc_free_fixed (domain); @@ -1976,20 +2115,159 @@ mono_domain_get_id (MonoDomain *domain) return domain->domain_id; } +/* + * mono_domain_alloc: + * + * LOCKING: Acquires the domain lock. + */ gpointer mono_domain_alloc (MonoDomain *domain, guint size) { + gpointer res; + + mono_domain_lock (domain); mono_perfcounters->loader_bytes += size; - return mono_mempool_alloc (domain->mp, size); + res = mono_mempool_alloc (domain->mp, size); + mono_domain_unlock (domain); + + return res; } +/* + * mono_domain_alloc0: + * + * LOCKING: Acquires the domain lock. + */ gpointer mono_domain_alloc0 (MonoDomain *domain, guint size) { + gpointer res; + + mono_domain_lock (domain); mono_perfcounters->loader_bytes += size; - return mono_mempool_alloc0 (domain->mp, size); + res = mono_mempool_alloc0 (domain->mp, size); + mono_domain_unlock (domain); + + return res; +} + +/* + * mono_domain_code_reserve: + * + * LOCKING: Acquires the domain lock. + */ +void* +mono_domain_code_reserve (MonoDomain *domain, int size) +{ + gpointer res; + + mono_domain_lock (domain); + res = mono_code_manager_reserve (domain->code_mp, size); + mono_domain_unlock (domain); + + return res; } +/* + * mono_domain_code_reserve_align: + * + * LOCKING: Acquires the domain lock. + */ +void* +mono_domain_code_reserve_align (MonoDomain *domain, int size, int alignment) +{ + gpointer res; + + mono_domain_lock (domain); + res = mono_code_manager_reserve_align (domain->code_mp, size, alignment); + mono_domain_unlock (domain); + + return res; +} + +/* + * mono_domain_code_commit: + * + * LOCKING: Acquires the domain lock. + */ +void +mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize) +{ + mono_domain_lock (domain); + mono_code_manager_commit (domain->code_mp, data, size, newsize); + mono_domain_unlock (domain); +} + +#if defined(__native_client_codegen__) && defined(__native_client__) +/* + * Given the temporary buffer (allocated by mono_domain_code_reserve) into which + * we are generating code, return a pointer to the destination in the dynamic + * code segment into which the code will be copied when mono_domain_code_commit + * is called. + * LOCKING: Acquires the domain lock. + */ +void * +nacl_domain_get_code_dest (MonoDomain *domain, void *data) +{ + void *dest; + mono_domain_lock (domain); + dest = nacl_code_manager_get_code_dest (domain->code_mp, data); + mono_domain_unlock (domain); + return dest; +} + +/* + * Convenience function which calls mono_domain_code_commit to validate and copy + * the code. The caller sets *buf_base and *buf_size to the start and size of + * the buffer (allocated by mono_domain_code_reserve), and *code_end to the byte + * after the last instruction byte. On return, *buf_base will point to the start + * of the copied in the code segment, and *code_end will point after the end of + * the copied code. + */ +void +nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end) +{ + guint8 *tmp = nacl_domain_get_code_dest (domain, *buf_base); + mono_domain_code_commit (domain, *buf_base, buf_size, *code_end - *buf_base); + *code_end = tmp + (*code_end - *buf_base); + *buf_base = tmp; +} + +#else + +/* no-op versions of Native Client functions */ + +void * +nacl_domain_get_code_dest (MonoDomain *domain, void *data) +{ + return data; +} + +void +nacl_domain_code_validate (MonoDomain *domain, guint8 **buf_base, int buf_size, guint8 **code_end) +{ +} + +#endif + +/* + * mono_domain_code_foreach: + * Iterate over the code thunks of the code manager of @domain. + * + * The @func callback MUST not take any locks. If it really needs to, it must respect + * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety + * LOCKING: Acquires the domain lock. + */ + +void +mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data) +{ + mono_domain_lock (domain); + mono_code_manager_foreach (domain->code_mp, func, user_data); + mono_domain_unlock (domain); +} + + void mono_context_set (MonoAppContext * new_context) { @@ -2014,7 +2292,8 @@ mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointe int size = GPOINTER_TO_INT (domain->static_data_array [1]); next = GPOINTER_TO_INT (domain->static_data_array [0]); if (next >= size) { - gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), NULL); + /* 'data' is allocated by alloc_fixed */ + gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * (size * 2), MONO_GC_ROOT_DESCR_FOR_FIXED (size * 2)); memcpy (new_array, domain->static_data_array, sizeof (gpointer) * size); size *= 2; new_array [1] = GINT_TO_POINTER (size); @@ -2023,7 +2302,7 @@ mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointe } } else { int size = 32; - gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, NULL); + gpointer *new_array = mono_gc_alloc_fixed (sizeof (gpointer) * size, MONO_GC_ROOT_DESCR_FOR_FIXED (size)); next = 2; new_array [0] = GINT_TO_POINTER (next); new_array [1] = GINT_TO_POINTER (size); @@ -2237,7 +2516,6 @@ app_config_parse (const char *exe_filename) GMarkupParseContext *context; char *text; gsize len; - struct stat buf; const char *bundled_config; char *config_filename; @@ -2249,11 +2527,6 @@ app_config_parse (const char *exe_filename) } else { config_filename = g_strconcat (exe_filename, ".config", NULL); - if (stat (config_filename, &buf) != 0) { - g_free (config_filename); - return NULL; - } - if (!g_file_get_contents (config_filename, &text, &len, NULL)) { g_free (config_filename); return NULL; @@ -2293,8 +2566,21 @@ get_runtime_by_version (const char *version) { int n; int max = G_N_ELEMENTS (supported_runtimes); - + gboolean do_partial_match; + int vlen; + + if (!version) + return NULL; + + vlen = strlen (version); + if (vlen >= 4 && version [1] - '0' >= 4) + do_partial_match = TRUE; + else + do_partial_match = FALSE; + for (n=0; n