From 2143e5488ec82a417eea36de90e817db035081a5 Mon Sep 17 00:00:00 2001 From: Ryan Lucia Date: Mon, 14 Sep 2020 21:55:45 -0400 Subject: [PATCH] [mono] Introduce MonoMemoryManager to hold memory previously owned by the domain (#41754) * Introduce MonoMemoryManager * Move things out of the domain * Update callers This does *not* handle cases where we call mono_domain_alloc and friends, just direct access to domain->mp etc. As of this, everything is allocated from the default ALC on netcore and the domain on legacy. * Update locks in domain_alloc functions * Take correct lock around mp * Introduce memory manager allocation helpers * Shorten mono_domain_default_memory_manager * Add memory_manager alloc nolock variants * Fix locking * More use of nolock functions * Add trailing newline to monovm.h This is obviously unrelated, but it was causing issues with my sed commands * mono_memory_manager -> mono_mem_manager Bit shorter at least, but I can cut it down further if deemed necessary * Add to msvc build * Fix mono/mono build * Fix test failure Oops * Remove erroneous returns * Store domain in memory manager, take domain lock * Build fixes * Remove comment * Free memory manager during domain unload * C++ fix * Don't double free * Remove designated initializer MSVC C++ fails it seems :( --- src/mono/mono/metadata/Makefile.am | 1 + src/mono/mono/metadata/appdomain.c | 18 +- src/mono/mono/metadata/assembly-load-context.c | 25 +++ src/mono/mono/metadata/assembly.c | 14 +- src/mono/mono/metadata/domain-internals.h | 54 ++++-- src/mono/mono/metadata/domain.c | 118 +++--------- src/mono/mono/metadata/loader-internals.h | 119 +++++++++++- src/mono/mono/metadata/memory-manager.c | 211 +++++++++++++++++++++ src/mono/mono/metadata/object.c | 28 +-- src/mono/mono/metadata/reflection-cache.h | 40 ++-- src/mono/mono/metadata/reflection.c | 83 +++----- src/mono/mono/metadata/sre.c | 7 +- src/mono/mono/mini/interp/interp.c | 21 +- src/mono/mono/mini/interp/transform.c | 3 +- src/mono/mono/mini/method-to-ir.c | 5 +- src/mono/mono/mini/mini-runtime.c | 2 +- src/mono/mono/mini/monovm.h | 2 +- src/mono/msvc/libmonoruntime-common.targets | 1 + .../msvc/libmonoruntime-common.targets.filters | 5 +- 19 files changed, 525 insertions(+), 232 deletions(-) create mode 100644 src/mono/mono/metadata/memory-manager.c diff --git a/src/mono/mono/metadata/Makefile.am b/src/mono/mono/metadata/Makefile.am index 76fa995..aa59336 100644 --- a/src/mono/mono/metadata/Makefile.am +++ b/src/mono/mono/metadata/Makefile.am @@ -427,6 +427,7 @@ common_sources = \ callspec.h \ callspec.c \ abi.c \ + memory-manager.c \ native-library.c \ native-library.h \ native-library-qcall.c \ diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c index 88686b6..0c3e89d 100644 --- a/src/mono/mono/metadata/appdomain.c +++ b/src/mono/mono/metadata/appdomain.c @@ -1052,10 +1052,11 @@ gboolean mono_domain_owns_vtable_slot (MonoDomain *domain, gpointer vtable_slot) { gboolean res; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); - mono_domain_lock (domain); - res = mono_mempool_contains_addr (domain->mp, vtable_slot); - mono_domain_unlock (domain); + mono_mem_manager_lock (memory_manager); + res = mono_mempool_contains_addr (memory_manager->mp, vtable_slot); + mono_mem_manager_unlock (memory_manager); return res; } @@ -3229,6 +3230,7 @@ unload_thread_main (void *arg) { unload_data *data = (unload_data*)arg; MonoDomain *domain = data->domain; + MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); int i; gsize result = 1; // failure @@ -3261,6 +3263,7 @@ unload_thread_main (void *arg) mono_loader_lock (); mono_domain_lock (domain); + mono_mem_manager_lock (memory_manager); /* * We need to make sure that we don't have any remsets * pointing into static data of the to-be-freed domain because @@ -3270,17 +3273,18 @@ unload_thread_main (void *arg) * now be null we won't do any unnecessary copies and after * the collection there won't be any more remsets. */ - for (i = 0; i < domain->class_vtable_array->len; ++i) - zero_static_data ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i)); + for (i = 0; i < memory_manager->class_vtable_array->len; ++i) + zero_static_data ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i)); #if !HAVE_BOEHM_GC mono_gc_collect (0); #endif - for (i = 0; i < domain->class_vtable_array->len; ++i) - clear_cached_vtable ((MonoVTable *)g_ptr_array_index (domain->class_vtable_array, i)); + for (i = 0; i < memory_manager->class_vtable_array->len; ++i) + clear_cached_vtable ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i)); deregister_reflection_info_roots (domain); mono_assembly_cleanup_domain_bindings (domain->domain_id); + mono_mem_manager_unlock (memory_manager); mono_domain_unlock (domain); mono_loader_unlock (); diff --git a/src/mono/mono/metadata/assembly-load-context.c b/src/mono/mono/metadata/assembly-load-context.c index ec46fbc..90b8d5e 100644 --- a/src/mono/mono/metadata/assembly-load-context.c +++ b/src/mono/mono/metadata/assembly-load-context.c @@ -23,6 +23,9 @@ mono_alc_init (MonoAssemblyLoadContext *alc, MonoDomain *domain, gboolean collec alc->domain = domain; alc->loaded_images = li; alc->loaded_assemblies = NULL; + alc->memory_manager = mono_mem_manager_create_singleton (alc, domain, collectible); + alc->generic_memory_managers = g_ptr_array_new (); + mono_coop_mutex_init (&alc->memory_managers_lock); alc->unloading = FALSE; alc->collectible = collectible; alc->pinvoke_scopes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); @@ -151,6 +154,16 @@ mono_alc_cleanup (MonoAssemblyLoadContext *alc) mono_alc_cleanup_assemblies (alc); + mono_mem_manager_free_singleton (alc->memory_manager, FALSE); + alc->memory_manager = NULL; + + /*for (int i = 0; i < alc->generic_memory_managers->len; i++) { + MonoGenericMemoryManager *memory_manager = (MonoGenericMemoryManager *)alc->generic_memory_managers->pdata [i]; + mono_mem_manager_free_generic (memory_manager, FALSE); + }*/ + g_ptr_array_free (alc->generic_memory_managers, TRUE); + mono_coop_mutex_destroy (&alc->memory_managers_lock); + mono_gchandle_free_internal (alc->gchandle); alc->gchandle = NULL; @@ -180,6 +193,18 @@ mono_alc_assemblies_unlock (MonoAssemblyLoadContext *alc) mono_coop_mutex_unlock (&alc->assemblies_lock); } +void +mono_alc_memory_managers_lock (MonoAssemblyLoadContext *alc) +{ + mono_coop_mutex_lock (&alc->memory_managers_lock); +} + +void +mono_alc_memory_managers_unlock (MonoAssemblyLoadContext *alc) +{ + mono_coop_mutex_unlock (&alc->memory_managers_lock); +} + gpointer ves_icall_System_Runtime_Loader_AssemblyLoadContext_InternalInitializeNativeALC (gpointer this_gchandle_ptr, MonoBoolean is_default_alc, MonoBoolean collectible, MonoError *error) { diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c index bc47b92..973555e 100644 --- a/src/mono/mono/metadata/assembly.c +++ b/src/mono/mono/metadata/assembly.c @@ -4339,6 +4339,7 @@ assembly_binding_info_parsed (MonoAssemblyBindingInfo *info, void *user_data) GSList *tmp; MonoAssemblyBindingInfo *info_tmp; MonoDomain *domain = (MonoDomain*)user_data; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); // linked with mono_domain_parse_assembly_bindings if (!domain) return; @@ -4355,14 +4356,14 @@ assembly_binding_info_parsed (MonoAssemblyBindingInfo *info, void *user_data) return; } - info_copy = (MonoAssemblyBindingInfo *)mono_mempool_alloc0 (domain->mp, sizeof (MonoAssemblyBindingInfo)); + info_copy = (MonoAssemblyBindingInfo *)mono_mem_manager_alloc0_nolock (memory_manager, sizeof (MonoAssemblyBindingInfo)); memcpy (info_copy, info, sizeof (MonoAssemblyBindingInfo)); if (info->name) - info_copy->name = mono_mempool_strdup (domain->mp, info->name); + info_copy->name = mono_mempool_strdup (memory_manager->mp, info->name); if (info->culture) - info_copy->culture = mono_mempool_strdup (domain->mp, info->culture); + info_copy->culture = mono_mempool_strdup (memory_manager->mp, info->culture); - domain->assembly_bindings = g_slist_append_mempool (domain->mp, domain->assembly_bindings, info_copy); + domain->assembly_bindings = g_slist_append_mempool (memory_manager->mp, domain->assembly_bindings, info_copy); } static int @@ -4425,7 +4426,11 @@ mono_domain_parse_assembly_bindings (MonoDomain *domain, int amajor, int aminor, { if (domain->assembly_bindings_parsed) return; + + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); // linked with assembly_binding_info_parsed + mono_domain_lock (domain); + mono_mem_manager_lock (memory_manager); if (!domain->assembly_bindings_parsed) { gchar *domain_config_file_path = mono_portability_find_file (domain_config_file_name, TRUE); @@ -4439,6 +4444,7 @@ mono_domain_parse_assembly_bindings (MonoDomain *domain, int amajor, int aminor, g_free (domain_config_file_path); } + mono_mem_manager_unlock (memory_manager); mono_domain_unlock (domain); } diff --git a/src/mono/mono/metadata/domain-internals.h b/src/mono/mono/metadata/domain-internals.h index 1ba9e6c..f31a9a7 100644 --- a/src/mono/mono/metadata/domain-internals.h +++ b/src/mono/mono/metadata/domain-internals.h @@ -339,8 +339,7 @@ struct _MonoDomain { * must taken first. */ MonoCoopMutex lock; - MonoMemPool *mp; - MonoCodeManager *code_mp; + /* * keep all the managed objects close to each other for the precise GC * For the Boehm GC we additionally keep close also other GC-tracked pointers. @@ -366,14 +365,7 @@ struct _MonoDomain { #define MONO_DOMAIN_FIRST_GC_TRACKED env MonoGHashTable *env; MonoGHashTable *ldstr_table; - /* hashtables for Reflection handles */ - MonoGHashTable *type_hash; - MonoConcGHashTable *refobject_hash; - /* maps class -> type initialization exception object */ - MonoGHashTable *type_init_exception_hash; - /* maps delegate trampoline addr -> delegate object */ - MonoGHashTable *delegate_hash_table; -#define MONO_DOMAIN_LAST_GC_TRACKED delegate_hash_table +#define MONO_DOMAIN_LAST_GC_TRACKED ldstr_table guint32 state; /* Needed by Thread:GetDomainID() */ gint32 domain_id; @@ -388,7 +380,6 @@ struct _MonoDomain { GSList *domain_assemblies; MonoAssembly *entry_assembly; char *friendly_name; - GPtrArray *class_vtable_array; /* maps remote class key -> MonoRemoteClass */ GHashTable *proxy_vtable_hash; /* Protected by 'jit_code_hash_lock' */ @@ -418,7 +409,7 @@ struct _MonoDomain { * This must be a GHashTable, since these objects can't be finalized * if the hashtable contains a GC visible reference to them. */ - GHashTable *finalizable_objects_hash; + GHashTable *finalizable_objects_hash; // TODO: this needs to be moved for unloadability with non-sgen gc /* Protects the three hashes above */ mono_mutex_t finalizable_objects_hash_lock; @@ -455,7 +446,7 @@ struct _MonoDomain { /* Cache function pointers for architectures */ /* that require wrappers */ - GHashTable *ftnptrs_hash; + GHashTable *ftnptrs_hash; // TODO: need to move? /* Maps MonoMethod* to weak links to DynamicMethod objects */ GHashTable *method_to_dyn_method; @@ -470,6 +461,11 @@ struct _MonoDomain { MonoAssemblyLoadContext *default_alc; MonoCoopMutex alcs_lock; /* Used when accessing 'alcs' */ #endif + +#ifndef ENABLE_NETCORE + // Holds domain code memory + MonoMemoryManager *memory_manager; +#endif }; typedef struct { @@ -565,6 +561,8 @@ mono_make_shadow_copy (const char *filename, MonoError *error); gboolean mono_is_shadow_copy_enabled (MonoDomain *domain, const gchar *dir_name); +// TODO: remove these on netcore, we should always be explicit about allocating from ALCs +//#ifndef ENABLE_NETCORE gpointer mono_domain_alloc (MonoDomain *domain, guint size); @@ -575,11 +573,6 @@ mono_domain_alloc0 (MonoDomain *domain, guint size); #define mono_domain_alloc0(domain, size) (g_cast (mono_domain_alloc0 ((domain), (size)))) -gpointer -mono_domain_alloc0_lock_free (MonoDomain *domain, guint size); - -#define mono_domain_alloc0_lock_free(domain, size) (g_cast (mono_domain_alloc0_lock_free ((domain), (size)))) - void* mono_domain_code_reserve (MonoDomain *domain, int size); @@ -595,6 +588,12 @@ mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize); void mono_domain_code_foreach (MonoDomain *domain, MonoCodeManagerFunc func, void *user_data); +//#endif + +gpointer +mono_domain_alloc0_lock_free (MonoDomain *domain, guint size); + +#define mono_domain_alloc0_lock_free(domain, size) (g_cast (mono_domain_alloc0_lock_free ((domain), (size)))) void mono_domain_unset (void); @@ -664,8 +663,6 @@ void mono_domain_set_options_from_config (MonoDomain *domain); int mono_framework_version (void); -void mono_reflection_cleanup_domain (MonoDomain *domain); - void mono_assembly_cleanup_domain_bindings (guint32 domain_id); MonoJitInfo* mono_jit_info_table_find_internal (MonoDomain *domain, gpointer addr, gboolean try_aot, gboolean allow_trampolines); @@ -721,6 +718,23 @@ mono_domain_ambient_alc (MonoDomain *domain) return mono_domain_default_alc (domain); } +static inline MonoMemoryManager * +mono_domain_memory_manager (MonoDomain *domain) +{ +#ifdef ENABLE_NETCORE + return (MonoMemoryManager *)mono_domain_default_alc (domain)->memory_manager; +#else + return domain->memory_manager; +#endif +} + +static inline MonoMemoryManager * +mono_domain_ambient_memory_manager (MonoDomain *domain) +{ + // FIXME: All callers of mono_domain_ambient_memory_manager should get a MemoryManager from their callers or context + return mono_domain_memory_manager (domain); +} + G_END_DECLS #endif /* __MONO_METADATA_DOMAIN_INTERNALS_H__ */ diff --git a/src/mono/mono/metadata/domain.c b/src/mono/mono/metadata/domain.c index f79975a..7671bea 100644 --- a/src/mono/mono/metadata/domain.c +++ b/src/mono/mono/metadata/domain.c @@ -432,14 +432,15 @@ mono_domain_create (void) MONO_PROFILER_RAISE (domain_loading, (domain)); - domain->mp = mono_mempool_new (); - domain->code_mp = mono_code_manager_new (); +#ifndef ENABLE_NETCORE + domain->memory_manager = (MonoMemoryManager *)mono_mem_manager_create_singleton (NULL, domain, TRUE); +#endif + domain->lock_free_mp = lock_free_mempool_new (); domain->env = mono_g_hash_table_new_type_internal ((GHashFunc)mono_string_hash_internal, (GCompareFunc)mono_string_equal_internal, MONO_HASH_KEY_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Environment Variable Table"); domain->domain_assemblies = 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); mono_jit_code_hash_init (&domain->jit_code_hash); domain->ldstr_table = mono_g_hash_table_new_type_internal ((GHashFunc)mono_string_hash_internal, (GCompareFunc)mono_string_equal_internal, MONO_HASH_KEY_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain String Pool Table"); @@ -1086,15 +1087,6 @@ mono_domain_assembly_open_internal (MonoDomain *domain, MonoAssemblyLoadContext return ass; } -static void -unregister_vtable_reflection_type (MonoVTable *vtable) -{ - MonoObject *type = (MonoObject *)vtable->type; - - if (type->vtable->klass != mono_defaults.runtimetype_class) - MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type); -} - /** * mono_domain_free: * \param domain the domain to release @@ -1146,23 +1138,7 @@ mono_domain_free (MonoDomain *domain, gboolean force) mono_g_hash_table_destroy (domain->env); domain->env = NULL; - 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 ((MonoVTable *)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; - } - if (domain->type_init_exception_hash) { - mono_g_hash_table_destroy (domain->type_init_exception_hash); - domain->type_init_exception_hash = NULL; - } + mono_mem_manager_free_objects_singleton ((MonoSingletonMemoryManager *)domain->memory_manager); for (tmp = domain->domain_assemblies; tmp; tmp = tmp->next) { MonoAssembly *ass = (MonoAssembly *)tmp->data; @@ -1230,8 +1206,6 @@ mono_domain_free (MonoDomain *domain, gboolean force) g_free (domain->friendly_name); domain->friendly_name = 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; mono_internal_hash_table_destroy (&domain->jit_code_hash); @@ -1249,25 +1223,15 @@ mono_domain_free (MonoDomain *domain, gboolean force) domain->jit_info_table = NULL; g_assert (!domain->jit_info_free_queue); - /* collect statistics */ - code_alloc = mono_code_manager_size (domain->code_mp, &code_size); + // Collect statistics + code_alloc = mono_code_manager_size (domain->memory_manager->code_mp, &code_size); total_domain_code_alloc += code_alloc; max_domain_code_alloc = MAX (max_domain_code_alloc, code_alloc); max_domain_code_size = MAX (max_domain_code_size, code_size); - if (debug_domain_unload) { - mono_mempool_invalidate (domain->mp); - mono_code_manager_invalidate (domain->code_mp); - } else { -#ifndef DISABLE_PERFCOUNTERS - /* FIXME: use an explicit subtraction method as soon as it's available */ - mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, -1 * 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; - } + mono_mem_manager_free_singleton ((MonoSingletonMemoryManager *)domain->memory_manager, debug_domain_unload); + domain->memory_manager = NULL; + lock_free_mempool_free (domain->lock_free_mp); domain->lock_free_mp = NULL; @@ -1367,41 +1331,27 @@ mono_domain_get_friendly_name (MonoDomain *domain) /* * mono_domain_alloc: * - * LOCKING: Acquires the domain lock. + * LOCKING: Acquires the default memory manager lock. */ gpointer (mono_domain_alloc) (MonoDomain *domain, guint size) { - gpointer res; + MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); - mono_domain_lock (domain); -#ifndef DISABLE_PERFCOUNTERS - mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, size); -#endif - res = mono_mempool_alloc (domain->mp, size); - mono_domain_unlock (domain); - - return res; + return mono_mem_manager_alloc (memory_manager, size); } /* * mono_domain_alloc0: * - * LOCKING: Acquires the domain lock. + * LOCKING: Acquires the default memory manager lock. */ gpointer (mono_domain_alloc0) (MonoDomain *domain, guint size) { - gpointer res; - - mono_domain_lock (domain); -#ifndef DISABLE_PERFCOUNTERS - mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, size); -#endif - res = mono_mempool_alloc0 (domain->mp, size); - mono_domain_unlock (domain); + MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); - return res; + return mono_mem_manager_alloc0 (memory_manager, size); } gpointer @@ -1413,48 +1363,40 @@ gpointer /* * mono_domain_code_reserve: * - * LOCKING: Acquires the domain lock. + * LOCKING: Acquires the default memory manager 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); + MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); - return res; + return mono_mem_manager_code_reserve (memory_manager, size); } /* * mono_domain_code_reserve_align: * - * LOCKING: Acquires the domain lock. + * LOCKING: Acquires the default memory manager lock. */ void* (mono_domain_code_reserve_align) (MonoDomain *domain, int size, int alignment) { - gpointer res; + MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); - mono_domain_lock (domain); - res = mono_code_manager_reserve_align (domain->code_mp, size, alignment); - mono_domain_unlock (domain); - - return res; + return mono_mem_manager_code_reserve_align (memory_manager, size, alignment); } /* * mono_domain_code_commit: * - * LOCKING: Acquires the domain lock. + * LOCKING: Acquires the default memory manager 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); + MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); + + mono_mem_manager_code_commit (memory_manager, data, size, newsize); } /* @@ -1463,15 +1405,15 @@ mono_domain_code_commit (MonoDomain *domain, void *data, int size, int newsize) * * 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. + * LOCKING: Acquires the default memory manager 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); + MonoMemoryManager *memory_manager = mono_domain_memory_manager (domain); + + mono_mem_manager_code_foreach (memory_manager, func, user_data); } /** diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index f61cad5..9a5e504 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -8,10 +8,14 @@ #include #include #include +#include +#include +#include #include -#include -#include +#include #include +#include +#include #ifdef ENABLE_NETCORE #if defined(TARGET_OSX) @@ -25,6 +29,11 @@ typedef struct _MonoLoadedImages MonoLoadedImages; typedef struct _MonoAssemblyLoadContext MonoAssemblyLoadContext; +typedef struct _MonoMemoryManager MonoMemoryManager; +typedef struct _MonoSingletonMemoryManager MonoSingletonMemoryManager; +#ifdef ENABLE_NETCORE +typedef struct _MonoGenericMemoryManager MonoGenericMemoryManager; +#endif struct _MonoBundledSatelliteAssembly { const char *name; @@ -45,22 +54,23 @@ struct _MonoDllMap { #endif #ifdef ENABLE_NETCORE -/* FIXME: this probably belongs somewhere else */ struct _MonoAssemblyLoadContext { MonoDomain *domain; MonoLoadedImages *loaded_images; GSList *loaded_assemblies; // If taking this with the domain assemblies_lock, always take this second MonoCoopMutex assemblies_lock; - /* Handle of the corresponding managed object. If the ALC is - * collectible, the handle is weak, otherwise it's strong. - */ + // Holds ALC-specific memory + MonoSingletonMemoryManager *memory_manager; + GPtrArray *generic_memory_managers; + // Protects generic_memory_managers; if taking this with the domain alcs_lock, always take this second + MonoCoopMutex memory_managers_lock; + // Handle of the corresponding managed object. If the ALC is + // collectible, the handle is weak, otherwise it's strong. MonoGCHandle gchandle; // Whether the ALC can be unloaded; should only be set at creation gboolean collectible; - // Set to TRUE when the unloading process has begun, ensures nothing else will use that ALC - // Maybe remove this? for now, should be helpful for debugging - // Alternatively, check for it in the various ALC functions and error if it's true when calling them + // Set to TRUE when the unloading process has begun gboolean unloading; // Used in native-library.c for the hash table below; do not access anywhere else MonoCoopMutex pinvoke_lock; @@ -69,6 +79,52 @@ struct _MonoAssemblyLoadContext { }; #endif /* ENABLE_NETCORE */ +struct _MonoMemoryManager { + MonoDomain *domain; + // Whether the MemoryManager can be unloaded on netcore; should only be set at creation + gboolean collectible; + // Whether this is a singleton or generic MemoryManager + gboolean is_generic; + // Whether the MemoryManager is in the process of being freed + gboolean freeing; + + // If taking this with the loader lock, always take this second + // Currently unused, we take the domain lock instead + MonoCoopMutex lock; + + MonoMemPool *mp; + MonoCodeManager *code_mp; + + GPtrArray *class_vtable_array; + + // !!! REGISTERED AS GC ROOTS !!! + // Hashtables for Reflection handles + MonoGHashTable *type_hash; + MonoConcGHashTable *refobject_hash; + // Maps class -> type initializaiton exception object + MonoGHashTable *type_init_exception_hash; + // Maps delegate trampoline addr -> delegate object + //MonoGHashTable *delegate_hash_table; + // End of GC roots +}; + +struct _MonoSingletonMemoryManager { + MonoMemoryManager memory_manager; + + // Parent ALC, NULL on framework + MonoAssemblyLoadContext *alc; +}; + +#ifdef ENABLE_NETCORE +struct _MonoGenericMemoryManager { + MonoMemoryManager memory_manager; + + // Parent ALCs + int n_alcs; + MonoAssemblyLoadContext **alcs; +}; +#endif + void mono_global_loader_data_lock (void); @@ -108,6 +164,12 @@ mono_alc_assemblies_lock (MonoAssemblyLoadContext *alc); void mono_alc_assemblies_unlock (MonoAssemblyLoadContext *alc); +void +mono_alc_memory_managers_lock (MonoAssemblyLoadContext *alc); + +void +mono_alc_memory_managers_unlock (MonoAssemblyLoadContext *alc); + gboolean mono_alc_is_default (MonoAssemblyLoadContext *alc); @@ -140,4 +202,43 @@ mono_alc_get_loaded_images (MonoAssemblyLoadContext *alc); MONO_API void mono_loader_save_bundled_library (int fd, uint64_t offset, uint64_t size, const char *destfname); +MonoSingletonMemoryManager * +mono_mem_manager_create_singleton (MonoAssemblyLoadContext *alc, MonoDomain *domain, gboolean collectible); + +void +mono_mem_manager_free_singleton (MonoSingletonMemoryManager *memory_manager, gboolean debug_unload); + +void +mono_mem_manager_free_objects_singleton (MonoSingletonMemoryManager *memory_manager); + +void +mono_mem_manager_lock (MonoMemoryManager *memory_manager); + +void +mono_mem_manager_unlock (MonoMemoryManager *memory_manager); + +void * +mono_mem_manager_alloc (MonoMemoryManager *memory_manager, guint size); + +void * +mono_mem_manager_alloc_nolock (MonoMemoryManager *memory_manager, guint size); + +void * +mono_mem_manager_alloc0 (MonoMemoryManager *memory_manager, guint size); + +void * +mono_mem_manager_alloc0_nolock (MonoMemoryManager *memory_manager, guint size); + +void * +mono_mem_manager_code_reserve (MonoMemoryManager *memory_manager, int size); + +void * +mono_mem_manager_code_reserve_align (MonoMemoryManager *memory_manager, int size, int newsize); + +void +mono_mem_manager_code_commit (MonoMemoryManager *memory_manager, void *data, int size, int newsize); + +void +mono_mem_manager_code_foreach (MonoMemoryManager *memory_manager, MonoCodeManagerFunc func, void *user_data); + #endif diff --git a/src/mono/mono/metadata/memory-manager.c b/src/mono/mono/metadata/memory-manager.c new file mode 100644 index 0000000..4d2b55d --- /dev/null +++ b/src/mono/mono/metadata/memory-manager.c @@ -0,0 +1,211 @@ +#include +#include +#include +#include + +static void +memory_manager_init (MonoMemoryManager *memory_manager, MonoDomain *domain, gboolean collectible) +{ + memory_manager->domain = domain; + memory_manager->freeing = FALSE; + + mono_coop_mutex_init_recursive (&memory_manager->lock); + + memory_manager->mp = mono_mempool_new (); + memory_manager->code_mp = mono_code_manager_new (); + + memory_manager->class_vtable_array = g_ptr_array_new (); + + // TODO: make these not linked to the domain for debugging + memory_manager->type_hash = mono_g_hash_table_new_type_internal ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Reflection Type Table"); + memory_manager->refobject_hash = mono_conc_g_hash_table_new_type (mono_reflected_hash, mono_reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Reflection Object Table"); + memory_manager->type_init_exception_hash = mono_g_hash_table_new_type_internal (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Type Initialization Exception Table"); +} + +MonoSingletonMemoryManager * +mono_mem_manager_create_singleton (MonoAssemblyLoadContext *alc, MonoDomain *domain, gboolean collectible) +{ + MonoSingletonMemoryManager *mem_manager = g_new0 (MonoSingletonMemoryManager, 1); + memory_manager_init ((MonoMemoryManager *)mem_manager, domain, collectible); + + mem_manager->memory_manager.is_generic = FALSE; + mem_manager->alc = alc; + + return mem_manager; +} + +static void +cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data) +{ + free_reflected_entry ((ReflectedEntry *)key); +} + +static void +unregister_vtable_reflection_type (MonoVTable *vtable) +{ + MonoObject *type = (MonoObject *)vtable->type; + + if (type->vtable->klass != mono_defaults.runtimetype_class) + MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type); +} + +// First phase of deletion +static void +memory_manager_delete_objects (MonoMemoryManager *memory_manager) +{ + memory_manager->freeing = TRUE; + + // Must be done before type_hash is freed + for (int i = 0; i < memory_manager->class_vtable_array->len; i++) + unregister_vtable_reflection_type ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i)); + + g_ptr_array_free (memory_manager->class_vtable_array, TRUE); + memory_manager->class_vtable_array = NULL; + mono_g_hash_table_destroy (memory_manager->type_hash); + memory_manager->type_hash = NULL; + mono_conc_g_hash_table_foreach (memory_manager->refobject_hash, cleanup_refobject_hash, NULL); + mono_conc_g_hash_table_destroy (memory_manager->refobject_hash); + memory_manager->refobject_hash = NULL; + mono_g_hash_table_destroy (memory_manager->type_init_exception_hash); + memory_manager->type_init_exception_hash = NULL; +} + +// Full deletion +static void +memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload) +{ + // Scan here to assert no lingering references in vtables? + + if (!memory_manager->freeing) + memory_manager_delete_objects (memory_manager); + + mono_coop_mutex_destroy (&memory_manager->lock); + + if (debug_unload) { + mono_mempool_invalidate (memory_manager->mp); + mono_code_manager_invalidate (memory_manager->code_mp); + } else { +#ifndef DISABLE_PERFCOUNTERS + /* FIXME: use an explicit subtraction method as soon as it's available */ + mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, -1 * mono_mempool_get_allocated (memory_manager->mp)); +#endif + mono_mempool_destroy (memory_manager->mp); + memory_manager->mp = NULL; + mono_code_manager_destroy (memory_manager->code_mp); + memory_manager->code_mp = NULL; + } +} + +void +mono_mem_manager_free_objects_singleton (MonoSingletonMemoryManager *memory_manager) +{ + g_assert (!memory_manager->memory_manager.freeing); + + memory_manager_delete_objects (&memory_manager->memory_manager); +} + +void +mono_mem_manager_free_singleton (MonoSingletonMemoryManager *memory_manager, gboolean debug_unload) +{ + g_assert (!memory_manager->memory_manager.is_generic); + + memory_manager_delete (&memory_manager->memory_manager, debug_unload); + g_free (memory_manager); +} + +void +mono_mem_manager_lock (MonoMemoryManager *memory_manager) +{ + //mono_coop_mutex_lock (&memory_manager->lock); + mono_domain_lock (memory_manager->domain); +} + +void +mono_mem_manager_unlock (MonoMemoryManager *memory_manager) +{ + //mono_coop_mutex_unlock (&memory_manager->lock); + mono_domain_unlock (memory_manager->domain); +} + +void * +mono_mem_manager_alloc (MonoMemoryManager *memory_manager, guint size) +{ + void *res; + + mono_mem_manager_lock (memory_manager); + res = mono_mem_manager_alloc_nolock (memory_manager, size); + mono_mem_manager_unlock (memory_manager); + + return res; +} + +void * +mono_mem_manager_alloc_nolock (MonoMemoryManager *memory_manager, guint size) +{ +#ifndef DISABLE_PERFCOUNTERS + mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, size); +#endif + return mono_mempool_alloc (memory_manager->mp, size); +} + +void * +mono_mem_manager_alloc0 (MonoMemoryManager *memory_manager, guint size) +{ + void *res; + + mono_mem_manager_lock (memory_manager); + res = mono_mem_manager_alloc0_nolock (memory_manager, size); + mono_mem_manager_unlock (memory_manager); + + return res; +} + +void * +mono_mem_manager_alloc0_nolock (MonoMemoryManager *memory_manager, guint size) +{ +#ifndef DISABLE_PERFCOUNTERS + mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, size); +#endif + return mono_mempool_alloc0 (memory_manager->mp, size); +} + + +void * +mono_mem_manager_code_reserve (MonoMemoryManager *memory_manager, int size) +{ + void *res; + + mono_mem_manager_lock (memory_manager); + res = mono_code_manager_reserve (memory_manager->code_mp, size); + mono_mem_manager_unlock (memory_manager); + + return res; +} + +void * +mono_mem_manager_code_reserve_align (MonoMemoryManager *memory_manager, int size, int alignment) +{ + void *res; + + mono_mem_manager_lock (memory_manager); + res = mono_code_manager_reserve_align (memory_manager->code_mp, size, alignment); + mono_mem_manager_unlock (memory_manager); + + return res; +} + +void +mono_mem_manager_code_commit (MonoMemoryManager *memory_manager, void *data, int size, int newsize) +{ + mono_mem_manager_lock (memory_manager); + mono_code_manager_commit (memory_manager->code_mp, data, size, newsize); + mono_mem_manager_unlock (memory_manager); +} + +void +mono_mem_manager_code_foreach (MonoMemoryManager *memory_manager, MonoCodeManagerFunc func, void *user_data) +{ + mono_mem_manager_lock (memory_manager); + mono_code_manager_foreach (memory_manager->code_mp, func, user_data); + mono_mem_manager_unlock (memory_manager); +} diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 4cf15fd..fcc7c58 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -331,6 +331,7 @@ get_type_init_exception_for_vtable (MonoVTable *vtable) ERROR_DECL (error); MonoDomain *domain = vtable->domain; MonoClass *klass = vtable->klass; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); MonoException *ex; gchar *full_name; @@ -342,10 +343,9 @@ get_type_init_exception_for_vtable (MonoVTable *vtable) * in the hash. */ ex = NULL; - mono_domain_lock (domain); - if (domain->type_init_exception_hash) - ex = (MonoException *)mono_g_hash_table_lookup (domain->type_init_exception_hash, klass); - mono_domain_unlock (domain); + mono_mem_manager_lock (memory_manager); + ex = (MonoException *)mono_g_hash_table_lookup (memory_manager->type_init_exception_hash, klass); + mono_mem_manager_unlock (memory_manager); if (!ex) { const char *klass_name_space = m_class_get_name_space (klass); @@ -446,6 +446,7 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) return TRUE; MonoClass *klass = vtable->klass; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); MonoImage *klass_image = m_class_get_image (klass); if (!mono_runtime_run_module_cctor(klass_image, vtable->domain, error)) { @@ -593,11 +594,9 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) * Store the exception object so it could be thrown on subsequent * accesses. */ - mono_domain_lock (domain); - if (!domain->type_init_exception_hash) - domain->type_init_exception_hash = mono_g_hash_table_new_type_internal (mono_aligned_addr_hash, NULL, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Type Initialization Exception Table"); - mono_g_hash_table_insert_internal (domain->type_init_exception_hash, klass, exc_to_throw); - mono_domain_unlock (domain); + mono_mem_manager_lock (memory_manager); + mono_g_hash_table_insert_internal (memory_manager->type_init_exception_hash, klass, exc_to_throw); + mono_mem_manager_unlock (memory_manager); } if (last_domain) @@ -1997,6 +1996,7 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro MonoVTable *vt; MonoClassRuntimeInfo *runtime_info; MonoClassField *field; + MonoMemoryManager *memory_manager; char *t; int i, vtable_slots; size_t imt_table_bytes; @@ -2283,7 +2283,10 @@ mono_class_create_runtime_vtable (MonoDomain *domain, MonoClass *klass, MonoErro /* class_vtable_array keeps an array of created vtables */ - g_ptr_array_add (domain->class_vtable_array, vt); + memory_manager = mono_domain_ambient_memory_manager (domain); + mono_mem_manager_lock (memory_manager); + g_ptr_array_add (memory_manager->class_vtable_array, vt); + mono_mem_manager_unlock (memory_manager); /* klass->runtime_info is protected by the loader lock, both when * it it enlarged and when it is stored info. */ @@ -2705,6 +2708,7 @@ mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *p MonoRemoteClass *rc; gpointer* key, *mp_key; char *name; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); error_init (error); @@ -2719,7 +2723,9 @@ mono_remote_class (MonoDomain *domain, MonoStringHandle class_name, MonoClass *p return rc; } - name = mono_string_to_utf8_mp (domain->mp, MONO_HANDLE_RAW (class_name), error); + mono_mem_manager_lock (memory_manager); + name = mono_string_to_utf8_mp (memory_manager->mp, MONO_HANDLE_RAW (class_name), error); + mono_mem_manager_unlock (memory_manager); if (!is_ok (error)) { g_free (key); mono_domain_unlock (domain); diff --git a/src/mono/mono/metadata/reflection-cache.h b/src/mono/mono/metadata/reflection-cache.h index 6a79296..02e5bd3 100644 --- a/src/mono/mono/metadata/reflection-cache.h +++ b/src/mono/mono/metadata/reflection-cache.h @@ -35,8 +35,8 @@ alloc_reflected_entry (MonoDomain *domain) { if (!mono_gc_is_moving ()) return g_new0 (ReflectedEntry, 1); - else - return (ReflectedEntry *)mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry)); + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); + return (ReflectedEntry *)mono_mem_manager_alloc_nolock (memory_manager, sizeof (ReflectedEntry)); } static inline void @@ -50,23 +50,21 @@ static inline MonoObject* cache_object (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObject* o) { MonoObject *obj; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); ReflectedEntry pe; pe.item = item; pe.refclass = klass; - mono_domain_lock (domain); - if (!domain->refobject_hash) - domain->refobject_hash = mono_conc_g_hash_table_new_type (mono_reflected_hash, mono_reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Reflection Object Table"); - - obj = (MonoObject*) mono_conc_g_hash_table_lookup (domain->refobject_hash, &pe); + mono_mem_manager_lock (memory_manager); + obj = (MonoObject *)mono_conc_g_hash_table_lookup (memory_manager->refobject_hash, &pe); if (obj == NULL) { ReflectedEntry *e = alloc_reflected_entry (domain); e->item = item; e->refclass = klass; - mono_conc_g_hash_table_insert (domain->refobject_hash, e, o); + mono_conc_g_hash_table_insert (memory_manager->refobject_hash, e, o); obj = o; } - mono_domain_unlock (domain); + mono_mem_manager_unlock (memory_manager); return obj; } @@ -74,23 +72,21 @@ cache_object (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObject* o static inline MonoObjectHandle cache_object_handle (MonoDomain *domain, MonoClass *klass, gpointer item, MonoObjectHandle o) { + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); ReflectedEntry pe; pe.item = item; pe.refclass = klass; - mono_domain_lock (domain); - if (!domain->refobject_hash) - domain->refobject_hash = mono_conc_g_hash_table_new_type (mono_reflected_hash, mono_reflected_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Reflection Object Table"); - - MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, (MonoObject*)mono_conc_g_hash_table_lookup (domain->refobject_hash, &pe)); + mono_mem_manager_lock (memory_manager); + MonoObjectHandle obj = MONO_HANDLE_NEW (MonoObject, (MonoObject *)mono_conc_g_hash_table_lookup (memory_manager->refobject_hash, &pe)); if (MONO_HANDLE_IS_NULL (obj)) { ReflectedEntry *e = alloc_reflected_entry (domain); e->item = item; e->refclass = klass; - mono_conc_g_hash_table_insert (domain->refobject_hash, e, MONO_HANDLE_RAW (o)); + mono_conc_g_hash_table_insert (memory_manager->refobject_hash, e, MONO_HANDLE_RAW (o)); MONO_HANDLE_ASSIGN (obj, o); } - mono_domain_unlock (domain); + mono_mem_manager_unlock (memory_manager); return obj; } @@ -100,14 +96,18 @@ cache_object_handle (MonoDomain *domain, MonoClass *klass, gpointer item, MonoOb static inline MonoObjectHandle check_object_handle (MonoDomain* domain, MonoClass *klass, gpointer item) { + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); + MonoObjectHandle obj_handle; ReflectedEntry e; e.item = item; e.refclass = klass; - MonoConcGHashTable *hash = domain->refobject_hash; - if (!hash) - return MONO_HANDLE_NEW (MonoObject, NULL); - return MONO_HANDLE_NEW (MonoObject, (MonoObject*)mono_conc_g_hash_table_lookup (hash, &e)); + mono_mem_manager_lock (memory_manager); + MonoConcGHashTable *hash = memory_manager->refobject_hash; + obj_handle = MONO_HANDLE_NEW (MonoObject, (MonoObject *)mono_conc_g_hash_table_lookup (hash, &e)); + mono_mem_manager_unlock (memory_manager); + + return obj_handle; } diff --git a/src/mono/mono/metadata/reflection.c b/src/mono/mono/metadata/reflection.c index 49c9078..d6097f3 100644 --- a/src/mono/mono/metadata/reflection.c +++ b/src/mono/mono/metadata/reflection.c @@ -184,36 +184,22 @@ mono_reflected_hash (gconstpointer a) { static void clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass) { - mono_domain_lock (domain); - if (domain->refobject_hash) { - ReflectedEntry pe; - gpointer orig_pe, orig_value; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); - pe.item = o; - pe.refclass = klass; + mono_mem_manager_lock (memory_manager); - if (mono_conc_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) { - mono_conc_g_hash_table_remove (domain->refobject_hash, &pe); - free_reflected_entry ((ReflectedEntry*)orig_pe); - } - } - mono_domain_unlock (domain); -} + gpointer orig_pe, orig_value; + ReflectedEntry pe; + pe.item = o; + pe.refclass = klass; -static void -cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data) -{ - free_reflected_entry ((ReflectedEntry*)key); -} -void -mono_reflection_cleanup_domain (MonoDomain *domain) -{ - if (domain->refobject_hash) { - mono_conc_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL); - mono_conc_g_hash_table_destroy (domain->refobject_hash); - domain->refobject_hash = NULL; + if (mono_conc_g_hash_table_lookup_extended (memory_manager->refobject_hash, &pe, &orig_pe, &orig_value)) { + mono_conc_g_hash_table_remove (memory_manager->refobject_hash, &pe); + free_reflected_entry ((ReflectedEntry *)orig_pe); } + + mono_mem_manager_unlock (memory_manager); } /** @@ -459,6 +445,7 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err g_assert (type != NULL); klass = mono_class_from_mono_type_internal (type); + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); /*we must avoid using @type as it might have come * from a mono_metadata_type_dup and the caller @@ -500,15 +487,9 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err } mono_loader_lock (); /*FIXME mono_class_init_internal and mono_class_vtable acquire it*/ - mono_domain_lock (domain); - if (!domain->type_hash) - domain->type_hash = mono_g_hash_table_new_type_internal ((GHashFunc)mono_metadata_type_hash, - (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC, MONO_ROOT_SOURCE_DOMAIN, domain, "Domain Reflection Type Table"); - if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (domain->type_hash, type))) { - mono_domain_unlock (domain); - mono_loader_unlock (); - return res; - } + mono_mem_manager_lock (memory_manager); + if ((res = (MonoReflectionType *)mono_g_hash_table_lookup (memory_manager->type_hash, type))) + goto leave; /*Types must be normalized so a generic instance of the GTD get's the same inner type. * For example in: Foo; Bar : Foo> @@ -520,15 +501,10 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err norm_type = mono_type_normalize (type); if (norm_type != type) { res = mono_type_get_object_checked (domain, norm_type, error); - if (!is_ok (error)) { - mono_domain_unlock (domain); - mono_loader_unlock (); - return NULL; - } - mono_g_hash_table_insert_internal (domain->type_hash, type, res); - mono_domain_unlock (domain); - mono_loader_unlock (); - return res; + goto_if_nok (error, leave); + + mono_g_hash_table_insert_internal (memory_manager->type_hash, type, res); + goto leave; } if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !m_class_was_typebuilder (type->data.generic_class->container_class)) { @@ -549,31 +525,26 @@ mono_type_get_object_checked (MonoDomain *domain, MonoType *type, MonoError *err /* I would have expected ReflectionTypeLoadException, but evidently .NET throws TLE in this case. */ mono_error_set_type_load_class (error, klass, "TypeBuilder.CreateType() not called for generic class %s", full_name); g_free (full_name); - mono_domain_unlock (domain); - mono_loader_unlock (); - return NULL; + res = NULL; + goto leave; } if (mono_class_has_ref_info (klass) && !m_class_was_typebuilder (klass) && !type->byref) { - mono_domain_unlock (domain); - mono_loader_unlock (); - return &mono_class_get_ref_info_raw (klass)->type; /* FIXME use handles */ + res = &mono_class_get_ref_info_raw (klass)->type; /* FIXME use handles */ + goto leave; } /* This is stored in vtables/JITted code so it has to be pinned */ res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.runtimetype_class, error); - if (!is_ok (error)) { - mono_domain_unlock (domain); - mono_loader_unlock (); - return NULL; - } + goto_if_nok (error, leave); res->type = type; - mono_g_hash_table_insert_internal (domain->type_hash, type, res); + mono_g_hash_table_insert_internal (memory_manager->type_hash, type, res); if (type->type == MONO_TYPE_VOID && !type->byref) domain->typeof_void = (MonoObject*)res; - mono_domain_unlock (domain); +leave: + mono_mem_manager_unlock (memory_manager); mono_loader_unlock (); return res; } diff --git a/src/mono/mono/metadata/sre.c b/src/mono/mono/metadata/sre.c index d2ee825..ad482f9 100644 --- a/src/mono/mono/metadata/sre.c +++ b/src/mono/mono/metadata/sre.c @@ -4086,12 +4086,15 @@ ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle ref_ * * Together with this we must ensure the contents of all instances to match the created type. */ - if (domain->type_hash && mono_class_is_gtd (klass)) { + if (mono_class_is_gtd (klass)) { + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (domain); struct remove_instantiations_user_data data; data.klass = klass; data.error = error; mono_error_assert_ok (error); - mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data); + mono_mem_manager_lock (memory_manager); + mono_g_hash_table_foreach_remove (memory_manager->type_hash, remove_instantiations_of_and_ensure_contents, &data); + mono_mem_manager_unlock (memory_manager); goto_if_nok (error, failure); } diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 195156b..555ea5a 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -671,17 +671,17 @@ typedef struct { InterpMethod *target_imethod; } InterpVTableEntry; -/* domain lock must be held */ +/* memory manager lock must be held */ static GSList* -append_imethod (MonoDomain *domain, GSList *list, InterpMethod *imethod, InterpMethod *target_imethod) +append_imethod (MonoMemoryManager *memory_manager, GSList *list, InterpMethod *imethod, InterpMethod *target_imethod) { GSList *ret; InterpVTableEntry *entry; - entry = (InterpVTableEntry*) mono_mempool_alloc (domain->mp, sizeof (InterpVTableEntry)); + entry = (InterpVTableEntry*) mono_mem_manager_alloc_nolock (memory_manager, sizeof (InterpVTableEntry)); entry->imethod = imethod; entry->target_imethod = target_imethod; - ret = g_slist_append_mempool (domain->mp, list, entry); + ret = g_slist_append_mempool (memory_manager->mp, list, entry); return ret; } @@ -726,6 +726,7 @@ static InterpMethod* // Inlining causes additional stack use in caller. get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset) { gpointer *table; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (vtable->domain); #ifndef DISABLE_REMOTING /* FIXME Remoting */ @@ -747,14 +748,14 @@ get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset) if (!table [offset]) { InterpMethod *target_imethod = get_virtual_method (imethod, vtable); /* Lazily initialize the method table slot */ - mono_domain_lock (vtable->domain); + mono_mem_manager_lock (memory_manager); if (!table [offset]) { if (imethod->method->is_inflated || offset < 0) - table [offset] = append_imethod (vtable->domain, NULL, imethod, target_imethod); + table [offset] = append_imethod (memory_manager, NULL, imethod, target_imethod); else table [offset] = (gpointer) ((gsize)target_imethod | 0x1); } - mono_domain_unlock (vtable->domain); + mono_mem_manager_unlock (memory_manager); } if ((gsize)table [offset] & 0x1) { @@ -766,10 +767,10 @@ get_virtual_method_fast (InterpMethod *imethod, MonoVTable *vtable, int offset) if (!target_imethod) { target_imethod = get_virtual_method (imethod, vtable); - mono_domain_lock (vtable->domain); + mono_mem_manager_lock (memory_manager); if (!get_target_imethod ((GSList*)table [offset], imethod)) - table [offset] = append_imethod (vtable->domain, (GSList*)table [offset], imethod, target_imethod); - mono_domain_unlock (vtable->domain); + table [offset] = append_imethod (memory_manager, (GSList*)table [offset], imethod, target_imethod); + mono_mem_manager_unlock (memory_manager); } return target_imethod; } diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index c25771f..f699f3d 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1046,8 +1046,9 @@ static void interp_generate_ipe_throw_with_msg (TransformData *td, MonoError *error_msg) { MonoJitICallInfo *info = &mono_get_jit_icall_info ()->mono_throw_invalid_program; + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (td->rtm->domain); - char *msg = mono_mempool_strdup (td->rtm->domain->mp, mono_error_get_message (error_msg)); + char *msg = mono_mempool_strdup (memory_manager->mp, mono_error_get_message (error_msg)); interp_add_ins (td, MINT_MONO_LDPTR); td->last_ins->data [0] = get_data_item_index (td, msg); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index 3f03487..f3c0a84 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -2317,7 +2317,10 @@ static void emit_invalid_program_with_msg (MonoCompile *cfg, MonoError *error_msg, MonoMethod *caller, MonoMethod *callee) { g_assert (!is_ok (error_msg)); - char *str = mono_mempool_strdup (cfg->domain->mp, mono_error_get_message (error_msg)); + MonoMemoryManager *memory_manager = mono_domain_ambient_memory_manager (cfg->domain); + mono_mem_manager_lock (memory_manager); + char *str = mono_mempool_strdup (memory_manager->mp, mono_error_get_message (error_msg)); + mono_mem_manager_unlock (memory_manager); MonoInst *iargs[1]; if (cfg->compile_aot) EMIT_NEW_LDSTRLITCONST (cfg, iargs [0], str); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 24f5402..57f0da6 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -4583,7 +4583,7 @@ mini_init (const char *filename, const char *runtime_version) if (mono_aot_only) { /* This helps catch code allocation requests */ - mono_code_manager_set_read_only (domain->code_mp); + mono_code_manager_set_read_only (mono_domain_ambient_memory_manager (domain)->code_mp); mono_marshal_use_aot_wrappers (TRUE); } diff --git a/src/mono/mono/mini/monovm.h b/src/mono/mono/mini/monovm.h index 7cb16e0..09fc3d3 100644 --- a/src/mono/mono/mini/monovm.h +++ b/src/mono/mono/mini/monovm.h @@ -17,4 +17,4 @@ monovm_execute_assembly (int argc, const char **argv, const char *managedAssembl MONO_API int monovm_shutdown (int *latchedExitCode); -#endif // _MONO_MINI_MONOVM_H_ \ No newline at end of file +#endif // _MONO_MINI_MONOVM_H_ diff --git a/src/mono/msvc/libmonoruntime-common.targets b/src/mono/msvc/libmonoruntime-common.targets index 9debec8..6006f78 100644 --- a/src/mono/msvc/libmonoruntime-common.targets +++ b/src/mono/msvc/libmonoruntime-common.targets @@ -73,6 +73,7 @@ + diff --git a/src/mono/msvc/libmonoruntime-common.targets.filters b/src/mono/msvc/libmonoruntime-common.targets.filters index b25559f..26ae534 100644 --- a/src/mono/msvc/libmonoruntime-common.targets.filters +++ b/src/mono/msvc/libmonoruntime-common.targets.filters @@ -558,7 +558,10 @@ Header Files$(MonoRuntimeFilterSubFolder)\common - + + + Source Files$MonoRuntimeFilterSubfolder\common + -- 2.7.4