未验证 提交 5a7ecc05 编写于 作者: Z Zoltan Varga 提交者: GitHub

[mono] Transition memory allocations from image sets to memory managers. (#50299)

* [mono] Transition memory allocations from image sets to memory managers.

* Move hashes from MonoImageSet to MonoGenericMemoryManager.
* Add a mono_mem_manager_get_generic () function which returns
  a memory manager for a set images. Same as the get_image_set ()
  function.
* Transition users of image sets to use MonoGenericMemoryManager.

* [mono] Unify MonoMemoryManager subclasses.

* Remove unused image set code.
上级 53d3bddc
......@@ -41,7 +41,7 @@ mono_alc_init (MonoAssemblyLoadContext *alc, gboolean collectible)
mono_loaded_images_init (li, alc);
alc->loaded_images = li;
alc->loaded_assemblies = NULL;
alc->memory_manager = mono_mem_manager_create_singleton (alc, collectible);
alc->memory_manager = mono_mem_manager_new (&alc, 1, collectible);
alc->generic_memory_managers = g_ptr_array_new ();
mono_coop_mutex_init (&alc->memory_managers_lock);
alc->unloading = FALSE;
......@@ -172,7 +172,7 @@ mono_alc_cleanup (MonoAssemblyLoadContext *alc)
mono_alc_cleanup_assemblies (alc);
mono_mem_manager_free_singleton (alc->memory_manager, FALSE);
mono_mem_manager_free (alc->memory_manager, FALSE);
alc->memory_manager = NULL;
/*for (int i = 0; i < alc->generic_memory_managers->len; i++) {
......
......@@ -824,7 +824,7 @@ mono_class_create_generic_inst (MonoGenericClass *gclass)
if (gclass->cached_class)
return gclass->cached_class;
klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
klass = (MonoClass *)mono_mem_manager_alloc0 ((MonoMemoryManager*)gclass->owner, sizeof (MonoClassGenericInst));
gklass = gclass->container_class;
......@@ -850,7 +850,6 @@ mono_class_create_generic_inst (MonoGenericClass *gclass)
klass->enumtype = gklass->enumtype;
klass->valuetype = gklass->valuetype;
if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
g_assert (gclass->context.class_inst);
g_assert (gclass->context.class_inst->type_argc > 0);
......@@ -1004,22 +1003,25 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
GSList *list, *rootlist = NULL;
int nsize;
char *name;
MonoImageSet* image_set;
MonoMemoryManager *mm;
if (rank > 1)
/* bounded only matters for one-dimensional arrays */
bounded = FALSE;
image = eclass->image;
image_set = class_kind_may_contain_generic_instances ((MonoTypeKind)eclass->class_kind) ? mono_metadata_get_image_set_for_class (eclass) : NULL;
// FIXME: Optimize this
mm = class_kind_may_contain_generic_instances ((MonoTypeKind)eclass->class_kind) ? mono_metadata_get_mem_manager_for_class (eclass) : NULL;
/* Check cache */
cached = NULL;
if (rank == 1 && !bounded) {
if (image_set) {
mono_image_set_lock (image_set);
cached = (MonoClass *)g_hash_table_lookup (image_set->szarray_cache, eclass);
mono_image_set_unlock (image_set);
if (mm) {
mono_mem_manager_lock (mm);
if (!mm->szarray_cache)
mm->szarray_cache = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, NULL);
cached = (MonoClass *)g_hash_table_lookup (mm->szarray_cache, eclass);
mono_mem_manager_unlock (mm);
} else {
/*
* This case is very frequent not just during compilation because of calls
......@@ -1033,9 +1035,11 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
mono_os_mutex_unlock (&image->szarray_cache_lock);
}
} else {
if (image_set) {
mono_image_set_lock (image_set);
rootlist = (GSList *)g_hash_table_lookup (image_set->array_cache, eclass);
if (mm) {
mono_mem_manager_lock (mm);
if (!mm->array_cache)
mm->array_cache = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, NULL);
rootlist = (GSList *)g_hash_table_lookup (mm->array_cache, eclass);
for (list = rootlist; list; list = list->next) {
k = (MonoClass *)list->data;
if ((m_class_get_rank (k) == rank) && (m_class_get_byval_arg (k)->type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
......@@ -1043,7 +1047,7 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
break;
}
}
mono_image_set_unlock (image_set);
mono_mem_manager_unlock (mm);
} else {
mono_loader_lock ();
if (!image->array_cache)
......@@ -1066,7 +1070,7 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
if (!parent->inited)
mono_class_init_internal (parent);
klass = image_set ? (MonoClass *)mono_image_set_alloc0 (image_set, sizeof (MonoClassArray)) : (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
klass = mm ? (MonoClass *)mono_mem_manager_alloc0 (mm, sizeof (MonoClassArray)) : (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
klass->image = image;
klass->name_space = eclass->name_space;
......@@ -1083,7 +1087,7 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
name [nsize + maxrank] = '*';
name [nsize + maxrank + bounded] = ']';
name [nsize + maxrank + bounded + 1] = 0;
klass->name = image_set ? mono_image_set_strdup (image_set, name) : mono_image_strdup (image, name);
klass->name = mm ? mono_mem_manager_strdup (mm, name) : mono_image_strdup (image, name);
g_free (name);
klass->type_token = 0;
......@@ -1135,7 +1139,7 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
klass->element_class = eclass;
if ((rank > 1) || bounded) {
MonoArrayType *at = image_set ? (MonoArrayType *)mono_image_set_alloc0 (image_set, sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
MonoArrayType *at = mm ? (MonoArrayType *)mono_mem_manager_alloc0 (mm, sizeof (MonoArrayType)) : (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
klass->_byval_arg.type = MONO_TYPE_ARRAY;
klass->_byval_arg.data.array = at;
at->eklass = eclass;
......@@ -1162,19 +1166,19 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
/* Check cache again */
cached = NULL;
if (rank == 1 && !bounded) {
if (image_set) {
mono_image_set_lock (image_set);
cached = (MonoClass *)g_hash_table_lookup (image_set->szarray_cache, eclass);
mono_image_set_unlock (image_set);
if (mm) {
mono_mem_manager_lock (mm);
cached = (MonoClass *)g_hash_table_lookup (mm->szarray_cache, eclass);
mono_mem_manager_unlock (mm);
} else {
mono_os_mutex_lock (&image->szarray_cache_lock);
cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
mono_os_mutex_unlock (&image->szarray_cache_lock);
}
} else {
if (image_set) {
mono_image_set_lock (image_set);
rootlist = (GSList *)g_hash_table_lookup (image_set->array_cache, eclass);
if (mm) {
mono_mem_manager_lock (mm);
rootlist = (GSList *)g_hash_table_lookup (mm->array_cache, eclass);
for (list = rootlist; list; list = list->next) {
k = (MonoClass *)list->data;
if ((m_class_get_rank (k) == rank) && (m_class_get_byval_arg (k)->type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
......@@ -1182,7 +1186,7 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
break;
}
}
mono_image_set_unlock (image_set);
mono_mem_manager_unlock (mm);
} else {
rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
for (list = rootlist; list; list = list->next) {
......@@ -1205,21 +1209,21 @@ mono_class_create_bounded_array (MonoClass *eclass, guint32 rank, gboolean bound
++class_array_count;
if (rank == 1 && !bounded) {
if (image_set) {
mono_image_set_lock (image_set);
g_hash_table_insert (image_set->szarray_cache, eclass, klass);
mono_image_set_unlock (image_set);
if (mm) {
mono_mem_manager_lock (mm);
g_hash_table_insert (mm->szarray_cache, eclass, klass);
mono_mem_manager_unlock (mm);
} else {
mono_os_mutex_lock (&image->szarray_cache_lock);
g_hash_table_insert (image->szarray_cache, eclass, klass);
mono_os_mutex_unlock (&image->szarray_cache_lock);
}
} else {
if (image_set) {
mono_image_set_lock (image_set);
if (mm) {
mono_mem_manager_lock (mm);
list = g_slist_append (rootlist, klass);
g_hash_table_insert (image_set->array_cache, eclass, list);
mono_image_set_unlock (image_set);
g_hash_table_insert (mm->array_cache, eclass, list);
mono_mem_manager_unlock (mm);
} else {
list = g_slist_append (rootlist, klass);
g_hash_table_insert (image->array_cache, eclass, list);
......@@ -1407,21 +1411,21 @@ mono_class_create_ptr (MonoType *type)
MonoClass *el_class;
MonoImage *image;
char *name;
MonoImageSet* image_set;
MonoMemoryManager *mm;
el_class = mono_class_from_mono_type_internal (type);
image = el_class->image;
image_set = class_kind_may_contain_generic_instances ((MonoTypeKind)el_class->class_kind) ? mono_metadata_get_image_set_for_class (el_class) : NULL;
if (image_set) {
mono_image_set_lock (image_set);
if (image_set->ptr_cache) {
if ((result = (MonoClass *)g_hash_table_lookup (image_set->ptr_cache, el_class))) {
mono_image_set_unlock (image_set);
return result;
}
}
mono_image_set_unlock (image_set);
// FIXME: Optimize this
mm = class_kind_may_contain_generic_instances ((MonoTypeKind)el_class->class_kind) ? mono_metadata_get_mem_manager_for_class (el_class) : NULL;
if (mm) {
mono_mem_manager_lock (mm);
if (!mm->ptr_cache)
mm->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
result = (MonoClass *)g_hash_table_lookup (mm->ptr_cache, el_class);
mono_mem_manager_unlock (mm);
if (result)
return result;
} else {
mono_image_lock (image);
if (image->ptr_cache) {
......@@ -1433,7 +1437,7 @@ mono_class_create_ptr (MonoType *type)
mono_image_unlock (image);
}
result = image_set ? (MonoClass *)mono_image_set_alloc0 (image_set, sizeof (MonoClassPointer)) : (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
result = mm ? (MonoClass *)mono_mem_manager_alloc0 (mm, sizeof (MonoClassPointer)) : (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
++class_pointer_count;
......@@ -1441,7 +1445,7 @@ mono_class_create_ptr (MonoType *type)
result->parent = NULL; /* no parent for PTR types */
result->name_space = el_class->name_space;
name = g_strdup_printf ("%s*", el_class->name);
result->name = image_set ? mono_image_set_strdup (image_set, name) : mono_image_strdup (image, name);
result->name = mm ? mono_mem_manager_strdup (mm, name) : mono_image_strdup (image, name);
result->class_kind = MONO_CLASS_POINTER;
g_free (name);
......@@ -1466,21 +1470,17 @@ mono_class_create_ptr (MonoType *type)
mono_class_setup_supertypes (result);
if (image_set) {
mono_image_set_lock (image_set);
if (image_set->ptr_cache) {
MonoClass *result2;
if ((result2 = (MonoClass *)g_hash_table_lookup (image_set->ptr_cache, el_class))) {
mono_image_set_unlock (image_set);
MONO_PROFILER_RAISE (class_failed, (result));
return result2;
}
}
else {
image_set->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
if (mm) {
mono_mem_manager_lock (mm);
MonoClass *result2;
result2 = (MonoClass *)g_hash_table_lookup (mm->ptr_cache, el_class);
if (!result2)
g_hash_table_insert (mm->ptr_cache, el_class, result);
mono_mem_manager_unlock (mm);
if (result2) {
MONO_PROFILER_RAISE (class_failed, (result));
return result2;
}
g_hash_table_insert (image_set->ptr_cache, el_class, result);
mono_image_set_unlock (image_set);
} else {
mono_image_lock (image);
if (image->ptr_cache) {
......
......@@ -405,7 +405,7 @@ struct _MonoMethodInflated {
} method;
MonoMethod *declaring; /* the generic method definition. */
MonoGenericContext context; /* The current instantiation */
MonoImageSet *owner; /* The image set that the inflated method belongs to. */
MonoMemoryManager *owner; /* The mem manager that the inflated method belongs to. */
};
/*
......@@ -419,12 +419,8 @@ struct _MonoGenericClass {
guint need_sync : 1; /* Only if dynamic. Need to be synchronized with its container class after its finished. */
MonoClass *cached_class; /* if present, the MonoClass corresponding to the instantiation. */
/*
* The image set which owns this generic class. Memory owned by the generic class
* including cached_class should be allocated from the mempool of the image set,
* so it is easy to free.
*/
MonoImageSet *owner;
/* The mem manager which owns this generic class. */
MonoMemoryManager *owner;
};
/* Additional details about a MonoGenericParam */
......@@ -901,11 +897,14 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
MonoMethod *
mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error);
MonoImageSet *
mono_metadata_get_image_set_for_class (MonoClass *klass);
MonoMemoryManager *
mono_metadata_get_mem_manager_for_type (MonoType *type);
MonoMemoryManager *
mono_metadata_get_mem_manager_for_class (MonoClass *klass);
MonoImageSet *
mono_metadata_get_image_set_for_method (MonoMethodInflated *method);
MonoMemoryManager*
mono_metadata_get_mem_manager_for_method (MonoMethodInflated *method);
MONO_API MonoMethodSignature *
mono_metadata_get_inflated_signature (MonoMethodSignature *sig, MonoGenericContext *context);
......
......@@ -1116,6 +1116,37 @@ mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContex
return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
}
static gboolean
inflated_method_equal (gconstpointer a, gconstpointer b)
{
const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
const MonoMethodInflated *mb = (const MonoMethodInflated *)b;
if (ma->declaring != mb->declaring)
return FALSE;
return mono_metadata_generic_context_equal (&ma->context, &mb->context);
}
static guint
inflated_method_hash (gconstpointer a)
{
const MonoMethodInflated *ma = (const MonoMethodInflated *)a;
return (mono_metadata_generic_context_hash (&ma->context) ^ mono_aligned_addr_hash (ma->declaring));
}
static void
free_inflated_method (MonoMethodInflated *imethod)
{
MonoMethod *method = (MonoMethod*)imethod;
if (method->signature)
mono_metadata_free_inflated_signature (method->signature);
if (method->wrapper_type)
g_free (((MonoMethodWrapper*)method)->method_data);
g_free (method);
}
/**
* mono_class_inflate_generic_method_full_checked:
* Instantiate method \p method with the generic context \p context.
......@@ -1178,12 +1209,14 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
iresult->context.class_inst = NULL;
MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
MonoMemoryManager *mm = mono_metadata_get_mem_manager_for_method (iresult);
// check cache
mono_image_set_lock (set);
cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
mono_image_set_unlock (set);
mono_mem_manager_lock (mm);
if (!mm->gmethod_cache)
mm->gmethod_cache = g_hash_table_new_full (inflated_method_hash, inflated_method_equal, NULL, (GDestroyNotify)free_inflated_method);
cached = (MonoMethodInflated *)g_hash_table_lookup (mm->gmethod_cache, iresult);
mono_mem_manager_unlock (mm);
if (cached) {
g_free (iresult);
......@@ -1276,14 +1309,14 @@ mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *k
*/
// check cache
mono_image_set_lock (set);
cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
mono_mem_manager_lock (mm);
cached = (MonoMethodInflated *)g_hash_table_lookup (mm->gmethod_cache, iresult);
if (!cached) {
g_hash_table_insert (set->gmethod_cache, iresult, iresult);
iresult->owner = set;
g_hash_table_insert (mm->gmethod_cache, iresult, iresult);
iresult->owner = mm;
cached = iresult;
}
mono_image_set_unlock (set);
mono_mem_manager_unlock (mm);
return (MonoMethod*)cached;
......
......@@ -2165,8 +2165,6 @@ mono_image_close_except_pools (MonoImage *image)
mono_image_invoke_unload_hook (image);
mono_metadata_clean_for_image (image);
#ifdef ENABLE_METADATA_UPDATE
mono_metadata_update_cleanup_on_close (image);
#endif
......
......@@ -16,6 +16,7 @@
#include <mono/utils/mono-coop-mutex.h>
#include <mono/utils/mono-error.h>
#include <mono/utils/mono-forward.h>
#include <mono/utils/mono-conc-hashtable.h>
#if defined(TARGET_OSX)
#define MONO_LOADER_LIBRARY_NAME "libcoreclr.dylib"
......@@ -30,8 +31,6 @@ G_BEGIN_DECLS
typedef struct _MonoLoadedImages MonoLoadedImages;
typedef struct _MonoAssemblyLoadContext MonoAssemblyLoadContext;
typedef struct _MonoMemoryManager MonoMemoryManager;
typedef struct _MonoSingletonMemoryManager MonoSingletonMemoryManager;
typedef struct _MonoGenericMemoryManager MonoGenericMemoryManager;
struct _MonoBundledSatelliteAssembly {
const char *name;
......@@ -51,6 +50,44 @@ struct _MonoDllMap {
};
#endif
typedef struct {
/*
* indexed by MonoMethodSignature
* Protected by the marshal lock
*/
GHashTable *delegate_invoke_cache;
GHashTable *delegate_begin_invoke_cache;
GHashTable *delegate_end_invoke_cache;
GHashTable *runtime_invoke_signature_cache;
GHashTable *runtime_invoke_sig_cache;
/*
* indexed by SignaturePointerPair
*/
GHashTable *delegate_abstract_invoke_cache;
GHashTable *delegate_bound_static_invoke_cache;
/*
* indexed by MonoMethod pointers
* Protected by the marshal lock
*/
GHashTable *runtime_invoke_method_cache;
GHashTable *managed_wrapper_cache;
GHashTable *native_wrapper_cache;
GHashTable *native_wrapper_aot_cache;
GHashTable *native_wrapper_check_cache;
GHashTable *native_wrapper_aot_check_cache;
GHashTable *native_func_wrapper_aot_cache;
GHashTable *native_func_wrapper_indirect_cache; /* Indexed by MonoMethodSignature. Protected by the marshal lock */
GHashTable *synchronized_cache;
GHashTable *unbox_wrapper_cache;
GHashTable *cominterop_invoke_cache;
GHashTable *cominterop_wrapper_cache; /* LOCKING: marshal lock */
GHashTable *thunk_invoke_cache;
} MonoWrapperCaches;
/* Lock-free allocator */
typedef struct {
guint8 *mem;
......@@ -68,7 +105,7 @@ struct _MonoAssemblyLoadContext {
// If taking this with the domain assemblies_lock, always take this second
MonoCoopMutex assemblies_lock;
// Holds ALC-specific memory
MonoSingletonMemoryManager *memory_manager;
MonoMemoryManager *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;
......@@ -117,7 +154,6 @@ struct _MonoMemoryManager {
/* Information maintained by the execution engine */
gpointer runtime_info;
// !!! REGISTERED AS GC ROOTS !!!
// Hashtables for Reflection handles
MonoGHashTable *type_hash;
MonoConcGHashTable *refobject_hash;
......@@ -125,22 +161,34 @@ struct _MonoMemoryManager {
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;
};
struct _MonoGenericMemoryManager {
MonoMemoryManager memory_manager;
/*
* Generic instances and aggregated custom modifiers depend on many alcs, and they need to be deleted if one
* of the alcs they depend on is unloaded. For example,
* List<Foo> depends on both List's alc and Foo's alc.
* A MemoryManager is the owner of all generic instances depending on the same set of
* alcs.
*/
// Parent ALCs
int n_alcs;
// Allocated from the mempool
MonoAssemblyLoadContext **alcs;
// Generic-specific caches
GHashTable *ginst_cache, *gmethod_cache, *gsignature_cache;
MonoConcurrentHashTable *gclass_cache;
/* mirror caches of ones already on MonoImage. These ones contain generics */
GHashTable *szarray_cache, *array_cache, *ptr_cache;
MonoWrapperCaches wrapper_caches;
GHashTable *aggregate_modifiers_cache;
/* Indexed by MonoGenericParam pointers */
GHashTable **gshared_types;
/* The length of the above array */
int gshared_types_len;
};
void
......@@ -236,14 +284,14 @@ mono_alc_get_all_loaded_assemblies (void);
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, gboolean collectible);
MonoMemoryManager *
mono_mem_manager_new (MonoAssemblyLoadContext **alcs, int nalcs, gboolean collectible);
void
mono_mem_manager_free_singleton (MonoSingletonMemoryManager *memory_manager, gboolean debug_unload);
mono_mem_manager_free (MonoMemoryManager *memory_manager, gboolean debug_unload);
void
mono_mem_manager_free_objects_singleton (MonoSingletonMemoryManager *memory_manager);
mono_mem_manager_free_objects (MonoMemoryManager *memory_manager);
void
mono_mem_manager_lock (MonoMemoryManager *memory_manager);
......@@ -285,6 +333,12 @@ mono_mem_manager_free_debug_info (MonoMemoryManager *memory_manager);
gboolean
mono_mem_manager_mp_contains_addr (MonoMemoryManager *memory_manager, gpointer addr);
MonoMemoryManager *
mono_mem_manager_get_generic (MonoImage **images, int nimages);
MonoMemoryManager*
mono_mem_manager_merge (MonoMemoryManager *mm1, MonoMemoryManager *mm2);
G_END_DECLS
#endif
......@@ -3,6 +3,7 @@
#include <mono/metadata/reflection-cache.h>
#include <mono/metadata/mono-hash-internals.h>
#include <mono/metadata/debug-internals.h>
#include <mono/utils/unlocked.h>
static LockFreeMempool*
lock_free_mempool_new (void)
......@@ -18,7 +19,7 @@ lock_free_mempool_free (LockFreeMempool *mp)
chunk = mp->chunks;
while (chunk) {
next = (LockFreeMempoolChunk *)chunk->prev;
mono_vfree (chunk, mono_pagesize (), MONO_MEM_ACCOUNT_DOMAIN);
mono_vfree (chunk, mono_pagesize (), MONO_MEM_ACCOUNT_MEM_MANAGER);
chunk = next;
}
g_free (mp);
......@@ -36,7 +37,7 @@ lock_free_mempool_chunk_new (LockFreeMempool *mp, int len)
size = mono_pagesize ();
while (size - sizeof (LockFreeMempoolChunk) < len)
size += mono_pagesize ();
chunk = (LockFreeMempoolChunk *)mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_DOMAIN);
chunk = (LockFreeMempoolChunk *)mono_valloc (0, size, MONO_MMAP_READ|MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_MEM_MANAGER);
g_assert (chunk);
chunk->mem = (guint8 *)ALIGN_PTR_TO ((char*)chunk + sizeof (LockFreeMempoolChunk), 16);
chunk->size = ((char*)chunk + size) - (char*)chunk->mem;
......@@ -90,12 +91,15 @@ lock_free_mempool_alloc0 (LockFreeMempool *mp, guint size)
return res;
}
static void
memory_manager_init (MonoMemoryManager *memory_manager, gboolean collectible)
MonoMemoryManager*
mono_mem_manager_new (MonoAssemblyLoadContext **alcs, int nalcs, gboolean collectible)
{
MonoDomain *domain = mono_get_root_domain ();
MonoMemoryManager *memory_manager;
memory_manager->freeing = FALSE;
memory_manager = g_new0 (MonoMemoryManager, 1);
memory_manager->collectible = collectible;
memory_manager->n_alcs = nalcs;
mono_coop_mutex_init_recursive (&memory_manager->lock);
mono_os_mutex_init (&memory_manager->mp_mutex);
......@@ -104,6 +108,9 @@ memory_manager_init (MonoMemoryManager *memory_manager, gboolean collectible)
memory_manager->code_mp = mono_code_manager_new ();
memory_manager->lock_free_mp = lock_free_mempool_new ();
memory_manager->alcs = mono_mempool_alloc0 (memory_manager->_mp, sizeof (MonoAssemblyLoadContext *) * nalcs);
memcpy (memory_manager->alcs, alcs, sizeof (MonoAssemblyLoadContext *) * nalcs);
memory_manager->class_vtable_array = g_ptr_array_new ();
// TODO: make these not linked to the domain for debugging
......@@ -113,18 +120,8 @@ memory_manager_init (MonoMemoryManager *memory_manager, gboolean collectible)
if (mono_get_runtime_callbacks ()->init_mem_manager)
mono_get_runtime_callbacks ()->init_mem_manager (memory_manager);
}
MonoSingletonMemoryManager *
mono_mem_manager_create_singleton (MonoAssemblyLoadContext *alc, gboolean collectible)
{
MonoSingletonMemoryManager *mem_manager = g_new0 (MonoSingletonMemoryManager, 1);
memory_manager_init ((MonoMemoryManager *)mem_manager, collectible);
mem_manager->memory_manager.is_generic = FALSE;
mem_manager->alc = alc;
return mem_manager;
return memory_manager;
}
static void
......@@ -198,19 +195,19 @@ memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload)
}
void
mono_mem_manager_free_objects_singleton (MonoSingletonMemoryManager *memory_manager)
mono_mem_manager_free_objects (MonoMemoryManager *memory_manager)
{
g_assert (!memory_manager->memory_manager.freeing);
g_assert (!memory_manager->freeing);
memory_manager_delete_objects (&memory_manager->memory_manager);
memory_manager_delete_objects (memory_manager);
}
void
mono_mem_manager_free_singleton (MonoSingletonMemoryManager *memory_manager, gboolean debug_unload)
mono_mem_manager_free (MonoMemoryManager *memory_manager, gboolean debug_unload)
{
g_assert (!memory_manager->memory_manager.is_generic);
g_assert (!memory_manager->is_generic);
memory_manager_delete (&memory_manager->memory_manager, debug_unload);
memory_manager_delete (memory_manager, debug_unload);
g_free (memory_manager);
}
......@@ -344,3 +341,207 @@ gpointer
{
return lock_free_mempool_alloc0 (memory_manager->lock_free_mp, size);
}
//107, 131, 163
#define HASH_TABLE_SIZE 163
static MonoMemoryManager *mem_manager_cache [HASH_TABLE_SIZE];
static gint32 mem_manager_cache_hit, mem_manager_cache_miss;
static guint32
mix_hash (uintptr_t source)
{
unsigned int hash = source;
// Actual hash
hash = (((hash * 215497) >> 16) ^ ((hash * 1823231) + hash));
// Mix in highest bits on 64-bit systems only
if (sizeof (source) > 4)
hash = hash ^ ((source >> 31) >> 1);
return hash;
}
static guint32
hash_alcs (MonoAssemblyLoadContext **alcs, int nalcs)
{
guint32 res = 0;
int i;
for (i = 0; i < nalcs; ++i)
res += mix_hash ((size_t)alcs [i]);
return res;
}
static gboolean
match_mem_manager (MonoMemoryManager *mm, MonoAssemblyLoadContext **alcs, int nalcs)
{
int j, k;
if (mm->n_alcs != nalcs)
return FALSE;
/* The order might differ so check all pairs */
for (j = 0; j < nalcs; ++j) {
for (k = 0; k < nalcs; ++k)
if (mm->alcs [k] == alcs [j])
break;
if (k == nalcs)
/* Not found */
break;
}
return j == nalcs;
}
static MonoMemoryManager*
mem_manager_cache_get (MonoAssemblyLoadContext **alcs, int nalcs)
{
guint32 hash_code = hash_alcs (alcs, nalcs);
int index = hash_code % HASH_TABLE_SIZE;
MonoMemoryManager *mm = mem_manager_cache [index];
if (!mm || !match_mem_manager (mm, alcs, nalcs)) {
UnlockedIncrement (&mem_manager_cache_miss);
return NULL;
}
UnlockedIncrement (&mem_manager_cache_hit);
return mm;
}
static void
mem_manager_cache_add (MonoMemoryManager *mem_manager)
{
guint32 hash_code = hash_alcs (mem_manager->alcs, mem_manager->n_alcs);
int index = hash_code % HASH_TABLE_SIZE;
mem_manager_cache [index] = mem_manager;
}
static MonoMemoryManager*
get_mem_manager_for_alcs (MonoAssemblyLoadContext **alcs, int nalcs)
{
MonoAssemblyLoadContext *alc;
GPtrArray *mem_managers;
MonoMemoryManager *res;
gboolean collectible;
/* Can happen for dynamic images */
if (nalcs == 0)
return mono_alc_get_default ()->memory_manager;
/* Common case */
if (nalcs == 1)
return alcs [0]->memory_manager;
collectible = FALSE;
for (int i = 0; i < nalcs; ++i)
collectible |= alcs [i]->collectible;
if (!collectible)
/* Can use the default alc */
return mono_alc_get_default ()->memory_manager;
// Check in a lock free cache
res = mem_manager_cache_get (alcs, nalcs);
if (res)
return res;
/*
* Find an existing mem manager for these ALCs.
* This can exist even if the cache lookup fails since the cache is very simple.
*/
/* We can search any ALC in the list, use the first one for now */
alc = alcs [0];
mono_alc_memory_managers_lock (alc);
mem_managers = alc->generic_memory_managers;
res = NULL;
for (int mindex = 0; mindex < mem_managers->len; ++mindex) {
MonoMemoryManager *mm = (MonoMemoryManager*)g_ptr_array_index (mem_managers, mindex);
if (match_mem_manager (mm, alcs, nalcs)) {
res = mm;
break;
}
}
mono_alc_memory_managers_unlock (alc);
if (res)
return res;
/* Create new mem manager */
res = mono_mem_manager_new (alcs, nalcs, collectible);
res->is_generic = TRUE;
/* The hashes are lazily inited in metadata.c */
/* Register it into its ALCs */
for (int i = 0; i < nalcs; ++i) {
mono_alc_memory_managers_lock (alcs [i]);
g_ptr_array_add (alcs [i]->generic_memory_managers, res);
mono_alc_memory_managers_unlock (alcs [i]);
}
mono_memory_barrier ();
mem_manager_cache_add (res);
return res;
}
/*
* mono_mem_manager_get_generic:
*
* Return a memory manager for allocating memory owned by the set of IMAGES.
*/
MonoMemoryManager*
mono_mem_manager_get_generic (MonoImage **images, int nimages)
{
MonoAssemblyLoadContext **alcs = g_newa (MonoAssemblyLoadContext*, nimages);
int nalcs, j;
/* Collect the set of ALCs owning the images */
nalcs = 0;
for (int i = 0; i < nimages; ++i) {
MonoAssemblyLoadContext *alc = mono_image_get_alc (images [i]);
if (!alc)
continue;
/* O(n^2), but shouldn't be a problem in practice */
for (j = 0; j < nalcs; ++j)
if (alcs [j] == alc)
break;
if (j == nalcs)
alcs [nalcs ++] = alc;
}
return get_mem_manager_for_alcs (alcs, nalcs);
}
/*
* mono_mem_manager_merge:
*
* Return a mem manager which depends on the ALCs of MM1/MM2.
*/
MonoMemoryManager*
mono_mem_manager_merge (MonoMemoryManager *mm1, MonoMemoryManager *mm2)
{
MonoAssemblyLoadContext **alcs = g_newa (MonoAssemblyLoadContext*, mm1->n_alcs + mm2->n_alcs);
memcpy (alcs, mm1->alcs, sizeof (MonoAssemblyLoadContext*) * mm1->n_alcs);
int nalcs = mm1->n_alcs;
/* O(n^2), but shouldn't be a problem in practice */
for (int i = 0; i < mm2->n_alcs; ++i) {
int j;
for (j = 0; j < mm1->n_alcs; ++j) {
if (mm2->alcs [i] == mm1->alcs [j])
break;
}
if (j == mm1->n_alcs)
alcs [nalcs ++] = mm2->alcs [i];
}
return get_mem_manager_for_alcs (alcs, nalcs);
}
......@@ -231,44 +231,6 @@ struct _MonoAssembly {
guint32 skipverification:2; /* Has SecurityPermissionFlag.SkipVerification permission */
};
typedef struct {
/*
* indexed by MonoMethodSignature
* Protected by the marshal lock
*/
GHashTable *delegate_invoke_cache;
GHashTable *delegate_begin_invoke_cache;
GHashTable *delegate_end_invoke_cache;
GHashTable *runtime_invoke_signature_cache;
GHashTable *runtime_invoke_sig_cache;
/*
* indexed by SignaturePointerPair
*/
GHashTable *delegate_abstract_invoke_cache;
GHashTable *delegate_bound_static_invoke_cache;
/*
* indexed by MonoMethod pointers
* Protected by the marshal lock
*/
GHashTable *runtime_invoke_method_cache;
GHashTable *managed_wrapper_cache;
GHashTable *native_wrapper_cache;
GHashTable *native_wrapper_aot_cache;
GHashTable *native_wrapper_check_cache;
GHashTable *native_wrapper_aot_check_cache;
GHashTable *native_func_wrapper_aot_cache;
GHashTable *native_func_wrapper_indirect_cache; /* Indexed by MonoMethodSignature. Protected by the marshal lock */
GHashTable *synchronized_cache;
GHashTable *unbox_wrapper_cache;
GHashTable *cominterop_invoke_cache;
GHashTable *cominterop_wrapper_cache; /* LOCKING: marshal lock */
GHashTable *thunk_invoke_cache;
} MonoWrapperCaches;
typedef struct {
const char* data;
guint32 size;
......@@ -584,42 +546,6 @@ struct _MonoImage {
mono_mutex_t lock;
};
/*
* Generic instances and aggregated custom modifiers depend on many images, and they need to be deleted if one
* of the images they depend on is unloaded. For example,
* List<Foo> depends on both List's image and Foo's image.
* A MonoImageSet is the owner of all generic instances depending on the same set of
* images.
*/
typedef struct {
int nimages;
MonoImage **images;
// Generic-specific caches
GHashTable *ginst_cache, *gmethod_cache, *gsignature_cache;
MonoConcurrentHashTable *gclass_cache;
/* mirror caches of ones already on MonoImage. These ones contain generics */
GHashTable *szarray_cache, *array_cache, *ptr_cache;
MonoWrapperCaches wrapper_caches;
GHashTable *aggregate_modifiers_cache;
/* Indexed by MonoGenericParam pointers */
GHashTable **gshared_types;
/* The length of the above array */
int gshared_types_len;
mono_mutex_t lock;
/*
* Memory for generic instances owned by this image set should be allocated from
* this mempool, using the mono_image_set_alloc family of functions.
*/
MonoMemPool *mempool;
} MonoImageSet;
enum {
MONO_SECTION_TEXT,
MONO_SECTION_RSRC,
......@@ -912,32 +838,6 @@ void
mono_image_load_enc_delta (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error);
#endif /* ENABLE_METADATA_UPDATE */
gpointer
mono_image_set_alloc (MonoImageSet *set, guint size);
gpointer
mono_image_set_alloc0 (MonoImageSet *set, guint size);
void
mono_image_set_lock (MonoImageSet *set);
void
mono_image_set_unlock (MonoImageSet *set);
char*
mono_image_set_strdup (MonoImageSet *set, const char *s);
MonoImageSet *
mono_metadata_get_image_set_for_aggregate_modifiers (MonoAggregateModContainer *amods);
MonoImageSet *
mono_metadata_get_image_set_for_type (MonoType *type);
MonoImageSet *
mono_metadata_merge_image_sets (MonoImageSet *set1, MonoImageSet *set2);
#define mono_image_set_new0(image,type,size) ((type *) mono_image_set_alloc0 (image, sizeof (type)* (size)))
gboolean
mono_image_load_cli_header (MonoImage *image, MonoCLIImageInfo *iinfo);
......@@ -959,9 +859,6 @@ mono_metadata_decode_row_dynamic_checked (const MonoDynamicImage *image, const M
MonoType*
mono_metadata_get_shared_type (MonoType *type);
void
mono_metadata_clean_for_image (MonoImage *image);
void
mono_metadata_clean_generic_classes_for_image (MonoImage *image);
......@@ -1193,12 +1090,6 @@ mono_metadata_parse_type_checked (MonoImage *m, MonoGenericContainer *container,
MonoGenericContainer *
mono_get_anonymous_container_for_image (MonoImage *image, gboolean is_mvar);
char *
mono_image_set_description (MonoImageSet *);
MonoImageSet *
mono_find_image_set_owner (void *ptr);
void
mono_loader_register_module (const char *name, MonoDl *module);
......
此差异已折叠。
......@@ -3964,14 +3964,14 @@ shared_gparam_equal (gconstpointer ka, gconstpointer kb)
MonoType*
mini_get_shared_gparam (MonoType *t, MonoType *constraint)
{
MonoImageSet *set;
MonoMemoryManager *mm;
MonoGenericParam *par = t->data.generic_param;
MonoGSharedGenericParam *copy, key;
MonoType *res;
MonoImage *image = NULL;
char *name;
set = mono_metadata_merge_image_sets (mono_metadata_get_image_set_for_type (t), mono_metadata_get_image_set_for_type (constraint));
mm = mono_mem_manager_merge (mono_metadata_get_mem_manager_for_type (t), mono_metadata_get_mem_manager_for_type (constraint));
memset (&key, 0, sizeof (key));
key.parent = par;
......@@ -3984,24 +3984,24 @@ mini_get_shared_gparam (MonoType *t, MonoType *constraint)
* Need a cache to ensure the newly created gparam
* is unique wrt T/CONSTRAINT.
*/
mono_image_set_lock (set);
if (!set->gshared_types) {
set->gshared_types_len = MONO_TYPE_INTERNAL;
set->gshared_types = g_new0 (GHashTable*, set->gshared_types_len);
}
if (!set->gshared_types [constraint->type])
set->gshared_types [constraint->type] = g_hash_table_new (shared_gparam_hash, shared_gparam_equal);
res = (MonoType *)g_hash_table_lookup (set->gshared_types [constraint->type], &key);
mono_image_set_unlock (set);
mono_mem_manager_lock (mm);
if (!mm->gshared_types) {
mm->gshared_types_len = MONO_TYPE_INTERNAL;
mm->gshared_types = g_new0 (GHashTable*, mm->gshared_types_len);
}
if (!mm->gshared_types [constraint->type])
mm->gshared_types [constraint->type] = g_hash_table_new (shared_gparam_hash, shared_gparam_equal);
res = (MonoType *)g_hash_table_lookup (mm->gshared_types [constraint->type], &key);
mono_mem_manager_unlock (mm);
if (res)
return res;
copy = (MonoGSharedGenericParam *)mono_image_set_alloc0 (set, sizeof (MonoGSharedGenericParam));
copy = (MonoGSharedGenericParam *)mono_mem_manager_alloc0 (mm, sizeof (MonoGSharedGenericParam));
memcpy (&copy->param, par, sizeof (MonoGenericParamFull));
copy->param.info.pklass = NULL;
// FIXME:
constraint = mono_metadata_type_dup (NULL, constraint);
name = get_shared_gparam_name (constraint->type, ((MonoGenericParamFull*)copy)->info.name);
copy->param.info.name = mono_image_set_strdup (set, name);
copy->param.info.name = mono_mem_manager_strdup (mm, name);
g_free (name);
copy->param.owner = par->owner;
......@@ -4012,10 +4012,10 @@ mini_get_shared_gparam (MonoType *t, MonoType *constraint)
res = mono_metadata_type_dup (NULL, t);
res->data.generic_param = (MonoGenericParam*)copy;
mono_image_set_lock (set);
mono_mem_manager_lock (mm);
/* Duplicates are ok */
g_hash_table_insert (set->gshared_types [constraint->type], copy, res);
mono_image_set_unlock (set);
g_hash_table_insert (mm->gshared_types [constraint->type], copy, res);
mono_mem_manager_unlock (mm);
return res;
}
......
......@@ -115,7 +115,7 @@ mono_mem_account_type_name (MonoMemAccountType type)
static const char *names[] = {
"code",
"hazard pointers",
"domain",
"mem manager",
"SGen internal",
"SGen nursery",
"SGen LOS",
......
......@@ -28,7 +28,7 @@ enum {
typedef enum {
MONO_MEM_ACCOUNT_CODE,
MONO_MEM_ACCOUNT_HAZARD_POINTERS,
MONO_MEM_ACCOUNT_DOMAIN,
MONO_MEM_ACCOUNT_MEM_MANAGER,
MONO_MEM_ACCOUNT_SGEN_INTERNAL,
MONO_MEM_ACCOUNT_SGEN_NURSERY,
MONO_MEM_ACCOUNT_SGEN_LOS,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册