Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoffeeFlux <CoffeeFlux@users.noreply.github.com>2020-09-14 17:55:25 +0300
committerCoffeeFlux <CoffeeFlux@users.noreply.github.com>2020-09-14 17:55:25 +0300
commit50bbd8339847a499357e63d5868c14b7ac9a925d (patch)
tree39daac75a8080976a7dd1678e20dbae5fec363ea
parentec3bd48aeb44cf1188c1b733218a0ee14efbe825 (diff)
[mono] Introduce MonoMemoryManager to hold memory previously owned by the domain
These commits: * Add the MonoMemoryManager struct * Create a memory manager in every domain on legacy * Create a memory manager in every ALC on netcore * Update callers accessing the fields in the domain directly * Remove lazy initialization on some of the old domain fields, in the interest in code simplification * Put the lock protecting the MemoryManager fields inside the struct itself Everything is still allocated at the domain level, either from the domain or default ALC depending on legacy vs netcore. This and the follow up PR have potential to expose racy locking logic by not taking the domain lock as frequently, but if that comes up we can just readd the domain lock as needed alongside the memory manager lock.
-rw-r--r--mono/metadata/Makefile.am1
-rw-r--r--mono/metadata/appdomain.c18
-rw-r--r--mono/metadata/assembly-load-context.c25
-rw-r--r--mono/metadata/assembly.c14
-rw-r--r--mono/metadata/domain-internals.h54
-rw-r--r--mono/metadata/domain.c118
-rw-r--r--mono/metadata/loader-internals.h119
-rw-r--r--mono/metadata/memory-manager.c211
-rw-r--r--mono/metadata/object.c28
-rw-r--r--mono/metadata/reflection-cache.h40
-rw-r--r--mono/metadata/reflection.c83
-rw-r--r--mono/metadata/sre.c7
-rw-r--r--mono/mini/interp/interp.c21
-rw-r--r--mono/mini/interp/transform.c3
-rw-r--r--mono/mini/method-to-ir.c5
-rw-r--r--mono/mini/mini-runtime.c2
-rw-r--r--mono/mini/monovm.h2
-rw-r--r--msvc/libmonoruntime-common.targets1
-rw-r--r--msvc/libmonoruntime-common.targets.filters5
19 files changed, 525 insertions, 232 deletions
diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am
index 76fa995d570..aa593365235 100644
--- a/mono/metadata/Makefile.am
+++ b/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/mono/metadata/appdomain.c b/mono/metadata/appdomain.c
index 88686b60828..0c3e89d9864 100644
--- a/mono/metadata/appdomain.c
+++ b/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/mono/metadata/assembly-load-context.c b/mono/metadata/assembly-load-context.c
index ec46fbc2b52..90b8d5e26e4 100644
--- a/mono/metadata/assembly-load-context.c
+++ b/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/mono/metadata/assembly.c b/mono/metadata/assembly.c
index bc47b92d97f..973555e68e9 100644
--- a/mono/metadata/assembly.c
+++ b/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/mono/metadata/domain-internals.h b/mono/metadata/domain-internals.h
index 1ba9e6cbc57..f31a9a73ead 100644
--- a/mono/metadata/domain-internals.h
+++ b/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/mono/metadata/domain.c b/mono/metadata/domain.c
index f79975aca2c..7671bea8e62 100644
--- a/mono/metadata/domain.c
+++ b/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/mono/metadata/loader-internals.h b/mono/metadata/loader-internals.h
index f61cad569fa..9a5e5045930 100644
--- a/mono/metadata/loader-internals.h
+++ b/mono/metadata/loader-internals.h
@@ -8,10 +8,14 @@
#include <glib.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/image.h>
+#include <mono/metadata/mempool-internals.h>
+#include <mono/metadata/mono-conc-hash.h>
+#include <mono/metadata/mono-hash.h>
#include <mono/metadata/object-forward.h>
-#include <mono/utils/mono-forward.h>
-#include <mono/utils/mono-error.h>
+#include <mono/utils/mono-codeman.h>
#include <mono/utils/mono-coop-mutex.h>
+#include <mono/utils/mono-error.h>
+#include <mono/utils/mono-forward.h>
#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/mono/metadata/memory-manager.c b/mono/metadata/memory-manager.c
new file mode 100644
index 00000000000..4d2b55d7141
--- /dev/null
+++ b/mono/metadata/memory-manager.c
@@ -0,0 +1,211 @@
+#include <mono/metadata/loader-internals.h>
+#include <mono/metadata/gc-internals.h>
+#include <mono/metadata/reflection-cache.h>
+#include <mono/metadata/mono-hash-internals.h>
+
+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/mono/metadata/object.c b/mono/metadata/object.c
index 4cf15fde2f2..fcc7c5886e4 100644
--- a/mono/metadata/object.c
+++ b/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/mono/metadata/reflection-cache.h b/mono/metadata/reflection-cache.h
index 6a792961c98..02e5bd37bf7 100644
--- a/mono/metadata/reflection-cache.h
+++ b/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/mono/metadata/reflection.c b/mono/metadata/reflection.c
index 49c907829eb..d6097f37572 100644
--- a/mono/metadata/reflection.c
+++ b/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<A,B>; Bar<A> : Foo<A, Bar<A>>
@@ -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/mono/metadata/sre.c b/mono/metadata/sre.c
index d2ee825173f..ad482f98330 100644
--- a/mono/metadata/sre.c
+++ b/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/mono/mini/interp/interp.c b/mono/mini/interp/interp.c
index 195156b0f6c..555ea5af0f1 100644
--- a/mono/mini/interp/interp.c
+++ b/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/mono/mini/interp/transform.c b/mono/mini/interp/transform.c
index c25771f3031..f699f3d4c40 100644
--- a/mono/mini/interp/transform.c
+++ b/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/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index 3f03487e6b2..f3c0a844b1a 100644
--- a/mono/mini/method-to-ir.c
+++ b/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/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c
index 24f54029812..57f0da61742 100644
--- a/mono/mini/mini-runtime.c
+++ b/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/mono/mini/monovm.h b/mono/mini/monovm.h
index 7cb16e0ce88..09fc3d3850f 100644
--- a/mono/mini/monovm.h
+++ b/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/msvc/libmonoruntime-common.targets b/msvc/libmonoruntime-common.targets
index 9debec84a0e..6006f787009 100644
--- a/msvc/libmonoruntime-common.targets
+++ b/msvc/libmonoruntime-common.targets
@@ -73,6 +73,7 @@
<ClCompile Include="$(MonoSourceLocation)\mono\metadata\marshal-ilgen.c" />
<ClInclude Include="$(MonoSourceLocation)\mono\metadata\marshal-ilgen.h" />
<ClInclude Include="$(MonoSourceLocation)\mono\metadata\marshal-internals.h" />
+ <ClCompile Include="$(MonoSourceLocation)\mono\metadata\memory-manager.c" />
<ClCompile Include="$(MonoSourceLocation)\mono\metadata\mempool.c" />
<ClInclude Include="$(MonoSourceLocation)\mono\metadata\mempool.h" />
<ClInclude Include="$(MonoSourceLocation)\mono\metadata\mempool-internals.h" />
diff --git a/msvc/libmonoruntime-common.targets.filters b/msvc/libmonoruntime-common.targets.filters
index b25559f1fb1..26ae534a071 100644
--- a/msvc/libmonoruntime-common.targets.filters
+++ b/msvc/libmonoruntime-common.targets.filters
@@ -558,7 +558,10 @@
</ClCompile>
<ClInclude Include="$(MonoSourceLocation)\mono\metadata\native-library.h">
<Filter>Header Files$(MonoRuntimeFilterSubFolder)\common</Filter>
- </ClInclude>
+ </ClInclude>
+ <ClCompile Include="$MonoSourceLocation)\mono\metadata\memory-manager.c">
+ <Filter>Source Files$MonoRuntimeFilterSubfolder\common</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup Label="config_sources">
<ClInclude Include="$(MonoSourceLocation)\mono\metadata\mono-config-dirs.h">