X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fdomain.c;h=447e860164654c913ca0d35a916a283a97728594;hb=5611946a3057c0c646256aa5b23e7040b8fc2cd4;hp=8b59cef9299ad4446a81385f5fcb2842bbc04a24;hpb=8f7a7a74e62e049e136d1b97d6ff60343fc820d2;p=mono.git diff --git a/mono/metadata/domain.c b/mono/metadata/domain.c index 8b59cef9299..447e8601646 100644 --- a/mono/metadata/domain.c +++ b/mono/metadata/domain.c @@ -17,12 +17,15 @@ #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -35,11 +38,12 @@ #include #include #include +#include #include #include #include -/* #define DEBUG_DOMAIN_UNLOAD */ +//#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 @@ -55,17 +59,25 @@ MONO_FAST_TLS_DECLARE(tls_appdomain); #define GET_APPDOMAIN() ((MonoDomain*)MONO_FAST_TLS_GET(tls_appdomain)) #define SET_APPDOMAIN(x) do { \ + MonoThreadInfo *info; \ MONO_FAST_TLS_SET (tls_appdomain,x); \ mono_native_tls_set_value (appdomain_thread_id, x); \ mono_gc_set_current_thread_appdomain (x); \ + info = mono_thread_info_current (); \ + if (info) \ + mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \ } while (FALSE) #else /* !MONO_HAVE_FAST_TLS */ #define GET_APPDOMAIN() ((MonoDomain *)mono_native_tls_get_value (appdomain_thread_id)) #define SET_APPDOMAIN(x) do { \ + MonoThreadInfo *info; \ mono_native_tls_set_value (appdomain_thread_id, x); \ mono_gc_set_current_thread_appdomain (x); \ + info = mono_thread_info_current (); \ + if (info) \ + mono_thread_info_tls_set (info, TLS_KEY_DOMAIN, (x)); \ } while (FALSE) #endif @@ -101,23 +113,10 @@ typedef struct { int startup_count; } AppConfigInfo; -/* - * AotModuleInfo: Contains information about AOT modules. - */ -typedef struct { - MonoImage *image; - gpointer start, end; -} AotModuleInfo; - static const MonoRuntimeInfo *current_runtime = NULL; static MonoJitInfoFindInAot jit_info_find_in_aot_func = NULL; -/* - * Contains information about AOT loaded code. - */ -static MonoAotModuleInfoTable *aot_modules = NULL; - /* This is the list of runtime versions supported by this JIT. */ static const MonoRuntimeInfo supported_runtimes[] = { @@ -126,6 +125,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} } }, }; @@ -146,9 +146,6 @@ get_runtimes_from_exe (const char *exe_file, MonoImage **exe_image, const MonoRu static const MonoRuntimeInfo* get_runtime_by_version (const char *version); -static MonoImage* -mono_jit_info_find_aot_module (guint8* addr); - MonoNativeTlsKey mono_domain_get_tls_key (void) { @@ -173,7 +170,7 @@ mono_domain_get_tls_offset (void) #define JIT_INFO_TABLE_HIGH_WATERMARK(n) ((n) * 5 / 6) #define JIT_INFO_TOMBSTONE_MARKER ((MonoMethod*)NULL) -#define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->method == JIT_INFO_TOMBSTONE_MARKER) +#define IS_JIT_INFO_TOMBSTONE(ji) ((ji)->d.method == JIT_INFO_TOMBSTONE_MARKER) #define JIT_INFO_TABLE_HAZARD_INDEX 0 #define JIT_INFO_HAZARD_INDEX 1 @@ -330,26 +327,11 @@ jit_info_table_chunk_index (MonoJitInfoTableChunk *chunk, MonoThreadHazardPointe return left; } -MonoJitInfo* -mono_jit_info_table_find (MonoDomain *domain, char *addr) +static MonoJitInfo* +jit_info_table_find (MonoJitInfoTable *table, MonoThreadHazardPointers *hp, gint8 *addr) { - MonoJitInfoTable *table; MonoJitInfo *ji; int chunk_pos, pos; - MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); - MonoImage *image; - - ++mono_stats.jit_info_table_lookup_count; - - /* First we have to get the domain's jit_info_table. This is - complicated by the fact that a writer might substitute a - new table and free the old one. What the writer guarantees - us is that it looks at the hazard pointers after it has - changed the jit_info_table pointer. So, if we guard the - table by a hazard pointer and make sure that the pointer is - still there after we've made it hazardous, we don't have to - worry about the writer freeing the table. */ - table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX); chunk_pos = jit_info_table_index (table, (gint8*)addr); g_assert (chunk_pos < table->num_chunks); @@ -375,7 +357,6 @@ mono_jit_info_table_find (MonoDomain *domain, char *addr) } if ((gint8*)addr >= (gint8*)ji->code_start && (gint8*)addr < (gint8*)ji->code_start + ji->code_size) { - mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); return ji; } @@ -392,22 +373,64 @@ mono_jit_info_table_find (MonoDomain *domain, char *addr) } while (chunk_pos < table->num_chunks); not_found: - if (!hp) - return NULL; + if (hp) + mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); + return NULL; +} - mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); - mono_hazard_pointer_clear (hp, JIT_INFO_HAZARD_INDEX); +/* + * mono_jit_info_table_find_internal: + * + * If TRY_AOT is FALSE, avoid loading information for missing methods from AOT images, which is currently not async safe. + * In this case, only those AOT methods will be found whose jit info is already loaded. + * ASYNC SAFETY: When called in an async context (mono_thread_info_is_async_context ()), this is async safe. + * In this case, the returned MonoJitInfo might not have metadata information, in particular, + * mono_jit_info_get_method () could fail. + */ +MonoJitInfo* +mono_jit_info_table_find_internal (MonoDomain *domain, char *addr, gboolean try_aot) +{ + MonoJitInfoTable *table; + MonoJitInfo *ji, *module_ji; + MonoThreadHazardPointers *hp = mono_hazard_pointer_get (); - ji = NULL; + ++mono_stats.jit_info_table_lookup_count; + + /* First we have to get the domain's jit_info_table. This is + complicated by the fact that a writer might substitute a + new table and free the old one. What the writer guarantees + us is that it looks at the hazard pointers after it has + changed the jit_info_table pointer. So, if we guard the + table by a hazard pointer and make sure that the pointer is + still there after we've made it hazardous, we don't have to + worry about the writer freeing the table. */ + table = get_hazardous_pointer ((gpointer volatile*)&domain->jit_info_table, hp, JIT_INFO_TABLE_HAZARD_INDEX); + + ji = jit_info_table_find (table, hp, (gint8*)addr); + if (hp) + mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); + if (ji) + return ji; /* 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); + if (try_aot && mono_root_domain && mono_root_domain->aot_modules) { + table = get_hazardous_pointer ((gpointer volatile*)&mono_root_domain->aot_modules, hp, JIT_INFO_TABLE_HAZARD_INDEX); + module_ji = jit_info_table_find (table, hp, (gint8*)addr); + if (module_ji) + ji = jit_info_find_in_aot_func (domain, module_ji->d.image, addr); + if (hp) + mono_hazard_pointer_clear (hp, JIT_INFO_TABLE_HAZARD_INDEX); + } return ji; } +MonoJitInfo* +mono_jit_info_table_find (MonoDomain *domain, char *addr) +{ + return mono_jit_info_table_find_internal (domain, addr, TRUE); +} + static G_GNUC_UNUSED void jit_info_table_check (MonoJitInfoTable *table) { @@ -664,22 +687,16 @@ jit_info_table_chunk_overflow (MonoJitInfoTable *table, MonoJitInfoTableChunk *c * the one we're looking for (i.e. we either find the element directly * or we end up to the left of it). */ -void -mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) +static void +jit_info_table_add (MonoDomain *domain, MonoJitInfoTable *volatile *table_ptr, MonoJitInfo *ji) { MonoJitInfoTable *table; - int chunk_pos, pos; MonoJitInfoTableChunk *chunk; + int chunk_pos, pos; int num_elements; int i; - g_assert (ji->method != NULL); - - mono_domain_lock (domain); - - ++mono_stats.jit_info_table_insert_count; - - table = domain->jit_info_table; + table = *table_ptr; restart: chunk_pos = jit_info_table_index (table, (gint8*)ji->code_start + ji->code_size); @@ -692,7 +709,7 @@ mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) /* Debugging code, should be removed. */ //jit_info_table_check (new_table); - domain->jit_info_table = new_table; + *table_ptr = new_table; mono_memory_barrier (); domain->num_jit_info_tables++; mono_thread_hazardous_free_or_queue (table, (MonoHazardousFreeFunc)jit_info_table_free, TRUE, FALSE); @@ -734,6 +751,18 @@ mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) /* Debugging code, should be removed. */ //jit_info_table_check (table); +} + +void +mono_jit_info_table_add (MonoDomain *domain, MonoJitInfo *ji) +{ + g_assert (ji->d.method != NULL); + + mono_domain_lock (domain); + + ++mono_stats.jit_info_table_insert_count; + + jit_info_table_add (domain, &domain->jit_info_table, ji); mono_domain_unlock (domain); } @@ -745,7 +774,7 @@ mono_jit_info_make_tombstone (MonoJitInfo *ji) tombstone->code_start = ji->code_start; tombstone->code_size = ji->code_size; - tombstone->method = JIT_INFO_TOMBSTONE_MARKER; + tombstone->d.method = JIT_INFO_TOMBSTONE_MARKER; return tombstone; } @@ -765,19 +794,13 @@ mono_jit_info_free_or_queue (MonoDomain *domain, MonoJitInfo *ji) } } -void -mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji) +static void +jit_info_table_remove (MonoJitInfoTable *table, MonoJitInfo *ji) { - MonoJitInfoTable *table; MonoJitInfoTableChunk *chunk; gpointer start = ji->code_start; int chunk_pos, pos; - mono_domain_lock (domain); - table = domain->jit_info_table; - - ++mono_stats.jit_info_table_remove_count; - chunk_pos = jit_info_table_index (table, start); g_assert (chunk_pos < table->num_chunks); @@ -808,90 +831,49 @@ mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji) /* Debugging code, should be removed. */ //jit_info_table_check (table); - - mono_jit_info_free_or_queue (domain, ji); - - mono_domain_unlock (domain); -} - -static MonoAotModuleInfoTable* -mono_aot_module_info_table_new (void) -{ - return g_array_new (FALSE, FALSE, sizeof (gpointer)); -} - -static int -aot_info_table_index (MonoAotModuleInfoTable *table, char *addr) -{ - int left = 0, right = table->len; - - while (left < right) { - int pos = (left + right) / 2; - AotModuleInfo *ainfo = g_array_index (table, gpointer, pos); - char *start = ainfo->start; - char *end = ainfo->end; - - if (addr < start) - right = pos; - else if (addr >= end) - left = pos + 1; - else - return pos; - } - - return left; } void -mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end) +mono_jit_info_table_remove (MonoDomain *domain, MonoJitInfo *ji) { - AotModuleInfo *ainfo = g_new0 (AotModuleInfo, 1); - int pos; - - ainfo->image = image; - ainfo->start = start; - ainfo->end = end; + MonoJitInfoTable *table; - mono_appdomains_lock (); + mono_domain_lock (domain); + table = domain->jit_info_table; - if (!aot_modules) - aot_modules = mono_aot_module_info_table_new (); + ++mono_stats.jit_info_table_remove_count; - pos = aot_info_table_index (aot_modules, start); + jit_info_table_remove (table, ji); - g_array_insert_val (aot_modules, pos, ainfo); + mono_jit_info_free_or_queue (domain, ji); - mono_appdomains_unlock (); + mono_domain_unlock (domain); } -static MonoImage* -mono_jit_info_find_aot_module (guint8* addr) +void +mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end) { - guint left = 0, right; - - if (!aot_modules) - return NULL; + MonoJitInfo *ji; mono_appdomains_lock (); - right = aot_modules->len; - while (left < right) { - guint pos = (left + right) / 2; - AotModuleInfo *ai = g_array_index (aot_modules, gpointer, pos); - - if (addr < (guint8*)ai->start) - right = pos; - else if (addr >= (guint8*)ai->end) - left = pos + 1; - else { - mono_appdomains_unlock (); - return ai->image; - } + /* + * 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); } - mono_appdomains_unlock (); + ji = g_new0 (MonoJitInfo, 1); + ji->d.image = image; + ji->code_start = start; + ji->code_size = (guint8*)end - (guint8*)start; + jit_info_table_add (mono_root_domain, &mono_root_domain->aot_modules, ji); - return NULL; + mono_appdomains_unlock (); } void @@ -915,7 +897,8 @@ mono_jit_info_get_code_size (MonoJitInfo* ji) MonoMethod* mono_jit_info_get_method (MonoJitInfo* ji) { - return ji->method; + g_assert (!ji->async); + return ji->d.method; } static gpointer @@ -923,7 +906,7 @@ jit_info_key_extract (gpointer value) { MonoJitInfo *info = (MonoJitInfo*)value; - return info->method; + return info->d.method; } static gpointer* @@ -952,96 +935,6 @@ mono_jit_info_get_generic_jit_info (MonoJitInfo *ji) return NULL; } -#ifdef USE_JUMP_TABLES - -#define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128 - -typedef struct MonoJumpTableChunk { - guint32 total; - guint32 active; - struct MonoJumpTableChunk *previous; - /* gpointer entries[total]; */ -} MonoJumpTableChunk; - -static MonoJumpTableChunk* g_jumptable = NULL; -#define mono_jumptable_lock() EnterCriticalSection (&jumptable_mutex) -#define mono_jumptable_unlock() LeaveCriticalSection (&jumptable_mutex) -static CRITICAL_SECTION jumptable_mutex; - -static MonoJumpTableChunk* -mono_create_jumptable_chunk (guint32 max_entries) -{ - guint32 size = sizeof (MonoJumpTableChunk) + max_entries * sizeof(gpointer); - MonoJumpTableChunk *chunk = (MonoJumpTableChunk*) g_new0 (guchar, size); - chunk->total = max_entries; - return chunk; -} - -void -mono_jumptable_init (void) -{ - if (g_jumptable == NULL) { - InitializeCriticalSection (&jumptable_mutex); - g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS); - } -} - -gpointer* -mono_jumptable_add_entry (void) -{ - return mono_jumptable_add_entries (1); -} - -gpointer* -mono_jumptable_add_entries (guint32 entries) -{ - guint32 index; - gpointer *result; - - mono_jumptable_init (); - mono_jumptable_lock (); - index = g_jumptable->active; - if (index + entries >= g_jumptable->total) { - /* - * Grow jumptable, by adding one more chunk. - * We cannot realloc jumptable, as there could be pointers - * to existing jump table entries in the code, so instead - * we just add one more chunk. - */ - guint32 max_entries = entries; - MonoJumpTableChunk *new_chunk; - - if (max_entries < DEFAULT_JUMPTABLE_CHUNK_ELEMENTS) - max_entries = DEFAULT_JUMPTABLE_CHUNK_ELEMENTS; - new_chunk = mono_create_jumptable_chunk (max_entries); - /* Link old jumptable, so that we could free it up later. */ - new_chunk->previous = g_jumptable; - g_jumptable = new_chunk; - index = 0; - } - g_jumptable->active = index + entries; - result = (gpointer*)((guchar*)g_jumptable + sizeof(MonoJumpTableChunk)) + index; - mono_jumptable_unlock(); - - return result; -} - -void -mono_jumptable_cleanup (void) -{ - if (g_jumptable) { - MonoJumpTableChunk *current = g_jumptable, *prev; - while (current != NULL) { - prev = current->previous; - g_free (current); - current = prev; - } - g_jumptable = NULL; - DeleteCriticalSection (&jumptable_mutex); - } -} -#endif - /* * mono_jit_info_get_generic_sharing_context: * @ji: a jit info @@ -1123,6 +1016,95 @@ mono_jit_info_get_cas_info (MonoJitInfo *ji) } } +#define ALIGN_TO(val,align) ((((guint64)val) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_PTR_TO(ptr,align) (gpointer)((((gssize)(ptr)) + (align - 1)) & (~(align - 1))) + +static LockFreeMempool* +lock_free_mempool_new (void) +{ + return g_new0 (LockFreeMempool, 1); +} + +static void +lock_free_mempool_free (LockFreeMempool *mp) +{ + LockFreeMempoolChunk *chunk, *next; + + chunk = mp->chunks; + while (chunk) { + next = chunk->prev; + mono_vfree (chunk, mono_pagesize ()); + chunk = next; + } + g_free (mp); +} + +/* + * This is async safe + */ +static LockFreeMempoolChunk* +lock_free_mempool_chunk_new (LockFreeMempool *mp, int len) +{ + LockFreeMempoolChunk *chunk, *prev; + int size; + + size = mono_pagesize (); + while (size - sizeof (LockFreeMempoolChunk) < len) + size += mono_pagesize (); + chunk = mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE); + g_assert (chunk); + chunk->mem = ALIGN_PTR_TO ((char*)chunk + sizeof (LockFreeMempoolChunk), 16); + chunk->size = ((char*)chunk + size) - (char*)chunk->mem; + chunk->pos = 0; + + /* Add to list of chunks lock-free */ + while (TRUE) { + prev = mp->chunks; + if (InterlockedCompareExchangePointer ((volatile gpointer*)&mp->chunks, chunk, prev) == prev) + break; + } + chunk->prev = prev; + + return chunk; +} + +/* + * This is async safe + */ +static gpointer +lock_free_mempool_alloc0 (LockFreeMempool *mp, guint size) +{ + LockFreeMempoolChunk *chunk; + gpointer res; + int oldpos; + + // FIXME: Free the allocator + + size = ALIGN_TO (size, 8); + chunk = mp->current; + if (!chunk) { + chunk = lock_free_mempool_chunk_new (mp, size); + mono_memory_barrier (); + /* Publish */ + mp->current = chunk; + } + + /* The code below is lock-free, 'chunk' is shared state */ + oldpos = InterlockedExchangeAdd (&chunk->pos, size); + if (oldpos + size > chunk->size) { + chunk = lock_free_mempool_chunk_new (mp, size); + g_assert (chunk->pos + size <= chunk->size); + res = chunk->mem; + chunk->pos += size; + mono_memory_barrier (); + mp->current = chunk; + } else { + res = (char*)chunk->mem + oldpos; + } + + return res; +} + void mono_install_create_domain_hook (MonoCreateDomainFunc func) { @@ -1295,6 +1277,7 @@ mono_domain_create (void) domain->mp = mono_mempool_new (); domain->code_mp = mono_code_manager_new (); + domain->lock_free_mp = lock_free_mempool_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->assembly_bindings = NULL; @@ -1391,6 +1374,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_classes_init (); mono_loader_init (); mono_reflection_init (); + mono_runtime_init_tls (); /* FIXME: When should we release this memory? */ MONO_GC_REGISTER_ROOT_FIXED (appdomains_list); @@ -1603,6 +1587,7 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.corlib, "System", "AppDomain"); g_assert (mono_defaults.appdomain_class != 0); +#ifndef DISABLE_REMOTING mono_defaults.transparent_proxy_class = mono_class_from_name ( mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "TransparentProxy"); g_assert (mono_defaults.transparent_proxy_class != 0); @@ -1611,6 +1596,15 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.corlib, "System.Runtime.Remoting.Proxies", "RealProxy"); g_assert (mono_defaults.real_proxy_class != 0); + mono_defaults.marshalbyrefobject_class = mono_class_from_name ( + mono_defaults.corlib, "System", "MarshalByRefObject"); + g_assert (mono_defaults.marshalbyrefobject_class != 0); + + mono_defaults.iremotingtypeinfo_class = mono_class_from_name ( + mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo"); + g_assert (mono_defaults.iremotingtypeinfo_class != 0); +#endif + mono_defaults.mono_method_message_class = mono_class_from_name ( mono_defaults.corlib, "System.Runtime.Remoting.Messaging", "MonoMethodMessage"); g_assert (mono_defaults.mono_method_message_class != 0); @@ -1643,18 +1637,6 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.corlib, "System.Runtime.InteropServices", "Marshal"); g_assert (mono_defaults.marshal_class != 0); - mono_defaults.iserializeable_class = mono_class_from_name ( - mono_defaults.corlib, "System.Runtime.Serialization", "ISerializable"); - g_assert (mono_defaults.iserializeable_class != 0); - - mono_defaults.serializationinfo_class = mono_class_from_name ( - mono_defaults.corlib, "System.Runtime.Serialization", "SerializationInfo"); - g_assert (mono_defaults.serializationinfo_class != 0); - - mono_defaults.streamingcontext_class = mono_class_from_name ( - mono_defaults.corlib, "System.Runtime.Serialization", "StreamingContext"); - g_assert (mono_defaults.streamingcontext_class != 0); - mono_defaults.typed_reference_class = mono_class_from_name ( mono_defaults.corlib, "System", "TypedReference"); g_assert (mono_defaults.typed_reference_class != 0); @@ -1663,18 +1645,10 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.corlib, "System", "RuntimeArgumentHandle"); g_assert (mono_defaults.argumenthandle_class != 0); - mono_defaults.marshalbyrefobject_class = mono_class_from_name ( - mono_defaults.corlib, "System", "MarshalByRefObject"); - g_assert (mono_defaults.marshalbyrefobject_class != 0); - mono_defaults.monitor_class = mono_class_from_name ( mono_defaults.corlib, "System.Threading", "Monitor"); g_assert (mono_defaults.monitor_class != 0); - mono_defaults.iremotingtypeinfo_class = mono_class_from_name ( - mono_defaults.corlib, "System.Runtime.Remoting", "IRemotingTypeInfo"); - g_assert (mono_defaults.iremotingtypeinfo_class != 0); - mono_defaults.runtimesecurityframe_class = mono_class_from_name ( mono_defaults.corlib, "System.Security", "RuntimeSecurityFrame"); @@ -1706,13 +1680,6 @@ mono_init_internal (const char *filename, const char *exe_filename, const char * mono_defaults.corlib, "System.Reflection", "CustomAttributeData"); /* these are initialized lazily when COM features are used */ -#ifndef DISABLE_COM - mono_defaults.variant_class = NULL; - mono_defaults.com_object_class = NULL; - mono_defaults.com_interop_proxy_class = NULL; - mono_defaults.iunknown_class = NULL; - mono_defaults.idispatch_class = NULL; -#endif mono_class_init (mono_defaults.array_class); mono_defaults.generic_nullable_class = mono_class_from_name ( @@ -1786,48 +1753,6 @@ mono_init_version (const char *domain_name, const char *version) return mono_init_internal (domain_name, NULL, version); } -#ifndef DISABLE_COM -/** - * mono_init_com_types: - * - * Initializes all types needed for COM Interop in mono_defaults structure. - */ -void -mono_init_com_types (void) -{ - static gboolean initialized = FALSE; - - if (initialized) - return; - - /* FIXME: do I need some threading protection here */ - - g_assert (mono_defaults.corlib); - - mono_defaults.variant_class = mono_class_from_name ( - mono_defaults.corlib, "System", "Variant"); - g_assert (mono_defaults.variant_class != 0); - - mono_defaults.com_object_class = mono_class_from_name ( - mono_defaults.corlib, "System", "__ComObject"); - g_assert (mono_defaults.com_object_class != 0); - - mono_defaults.com_interop_proxy_class = mono_class_from_name ( - mono_defaults.corlib, "Mono.Interop", "ComInteropProxy"); - g_assert (mono_defaults.com_interop_proxy_class != 0); - - mono_defaults.iunknown_class = mono_class_from_name ( - mono_defaults.corlib, "Mono.Interop", "IUnknown"); - g_assert (mono_defaults.iunknown_class != 0); - - mono_defaults.idispatch_class = mono_class_from_name ( - mono_defaults.corlib, "Mono.Interop", "IDispatch"); - g_assert (mono_defaults.idispatch_class != 0); - - initialized = TRUE; -} -#endif /*DISABLE_COM*/ - /** * mono_cleanup: * @@ -1847,10 +1772,6 @@ mono_cleanup (void) mono_images_cleanup (); mono_debug_cleanup (); mono_metadata_cleanup (); -#ifdef USE_JUMP_TABLES - mono_jumptable_cleanup (); -#endif - mono_native_tls_free (appdomain_thread_id); DeleteCriticalSection (&appdomains_mutex); @@ -2011,6 +1932,8 @@ mono_domain_free (MonoDomain *domain, gboolean force) { int code_size, code_alloc; GSList *tmp; + gpointer *p; + if ((domain == mono_root_domain) && !force) { g_warning ("cant unload root domain"); return; @@ -2054,6 +1977,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; @@ -2063,22 +1993,34 @@ 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); } + /* Have to zero out reference fields since they will be invalidated by the clear_domain () call below */ + for (p = (gpointer*)&domain->MONO_DOMAIN_FIRST_OBJECT; p < (gpointer*)&domain->MONO_DOMAIN_FIRST_GC_TRACKED; ++p) + *p = NULL; + /* This needs to be done before closing assemblies */ mono_gc_clear_domain (domain); + /* 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) + 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)) + tmp->data = NULL; + } + for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { MonoAssembly *ass = tmp->data; + if (!ass) + continue; + if (!ass->image || ass->image->dynamic) + 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)) tmp->data = NULL; @@ -2133,6 +2075,8 @@ mono_domain_free (MonoDomain *domain, gboolean force) * this will free them. */ mono_thread_hazardous_try_free_all (); + if (domain->aot_modules) + jit_info_table_free (domain->aot_modules); g_assert (domain->num_jit_info_tables == 1); jit_info_table_free (domain->jit_info_table); domain->jit_info_table = NULL; @@ -2156,6 +2100,8 @@ mono_domain_free (MonoDomain *domain, gboolean force) mono_code_manager_destroy (domain->code_mp); domain->code_mp = NULL; #endif + lock_free_mempool_free (domain->lock_free_mp); + domain->lock_free_mp = NULL; g_hash_table_destroy (domain->finalizable_objects_hash); domain->finalizable_objects_hash = NULL; @@ -2263,6 +2209,12 @@ mono_domain_alloc0 (MonoDomain *domain, guint size) return res; } +gpointer +mono_domain_alloc0_lock_free (MonoDomain *domain, guint size) +{ + return lock_free_mempool_alloc0 (domain->lock_free_mp, size); +} + /* * mono_domain_code_reserve: * @@ -2406,7 +2358,7 @@ mono_domain_add_class_static_data (MonoDomain *domain, MonoClass *klass, gpointe if (next >= size) { /* '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)); - mono_gc_memmove (new_array, domain->static_data_array, sizeof (gpointer) * size); + mono_gc_memmove_aligned (new_array, domain->static_data_array, sizeof (gpointer) * size); size *= 2; new_array [1] = GINT_TO_POINTER (size); mono_gc_free_fixed (domain->static_data_array);