Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[runtime] Add a memory manager for dynamic methods, use it to allocate some of the memory allocated by the runtime for dynamic methods. #42833

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/mono/mono/metadata/class-inlines.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,10 @@ m_method_is_wrapper (MonoMethod *method)
return method->wrapper_type != 0;
}

static inline gboolean
m_method_is_dynamic (MonoMethod *method)
{
return method->dynamic;
}

#endif
24 changes: 22 additions & 2 deletions src/mono/mono/metadata/class-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ struct _MonoMethodWrapper {
struct _MonoDynamicMethod {
MonoMethodWrapper method;
MonoAssembly *assembly;
/*
* Memory whose lifetime is equal to the lifetime of the dynamic method
* should be allocated from this memory manager.
*/
MonoMemoryManager *mem_manager;
};

struct _MonoMethodPInvoke {
Expand Down Expand Up @@ -1625,6 +1630,8 @@ m_class_alloc0 (MonoDomain *domain, MonoClass *klass, guint size)
static inline MonoMemoryManager*
m_method_get_mem_manager (MonoDomain *domain, MonoMethod *method)
{
if (method->dynamic)
return ((MonoDynamicMethod*)method)->mem_manager;
#ifdef ENABLE_NETCORE
// FIXME:
return mono_domain_memory_manager (domain);
Expand All @@ -1633,18 +1640,31 @@ m_method_get_mem_manager (MonoDomain *domain, MonoMethod *method)
#endif
}

static inline void *
/*
* m_method_alloc:
*
* Allocate memory whose lifetime is equal to:
* - domain+method, if domain != NULL
* - method, if domain == NULL.
*/
static inline void*
m_method_alloc (MonoDomain *domain, MonoMethod *method, guint size)
{
return mono_mem_manager_alloc (m_method_get_mem_manager (domain, method), size);
}

static inline void *
static inline void*
m_method_alloc0 (MonoDomain *domain, MonoMethod *method, guint size)
{
return mono_mem_manager_alloc0 (m_method_get_mem_manager (domain, method), size);
}

static inline char*
m_method_strdup (MonoDomain *domain, MonoMethod *method, const char *s)
{
return mono_mem_manager_strdup (m_method_get_mem_manager (domain, method), s);
}

// Enum and static storage for JIT icalls.
#include "jit-icall-reg.h"

Expand Down
8 changes: 8 additions & 0 deletions src/mono/mono/metadata/loader-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ struct _MonoMemoryManager {
gboolean is_generic;
// Whether the MemoryManager is in the process of being freed
gboolean freeing;
// Whenever this is owned by a dynamic method
gboolean dynamic_method;

// If taking this with the loader lock, always take this second
// Currently unused, we take the domain lock instead
Expand Down Expand Up @@ -213,6 +215,12 @@ mono_mem_manager_free_singleton (MonoSingletonMemoryManager *memory_manager, gbo
void
mono_mem_manager_free_objects_singleton (MonoSingletonMemoryManager *memory_manager);

MonoMemoryManager *
mono_mem_manager_create_dynamic_method (MonoDomain *domain);

void
mono_mem_manager_free_dynamic_method (MonoMemoryManager *memory_manager);

void
mono_mem_manager_lock (MonoMemoryManager *memory_manager);

Expand Down
5 changes: 4 additions & 1 deletion src/mono/mono/metadata/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -1402,9 +1402,10 @@ mono_free_method (MonoMethod *method)
/* mono_metadata_free_method_signature (method->signature); */
/* g_free (method->signature); */
}

if (method_is_dynamic (method)) {
MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
MonoMemoryManager *mem_manager = ((MonoDynamicMethod*)method)->mem_manager;
int i;

mono_marshal_free_dynamic_wrappers (method);
Expand All @@ -1422,6 +1423,8 @@ mono_free_method (MonoMethod *method)
g_free (mw->method_data);
g_free (method->signature);
g_free (method);

mono_mem_manager_free_dynamic_method (mem_manager);
}
}

Expand Down
55 changes: 41 additions & 14 deletions src/mono/mono/metadata/memory-manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,61 @@
#include <mono/metadata/mono-hash-internals.h>

static void
memory_manager_init (MonoMemoryManager *memory_manager, MonoDomain *domain, gboolean collectible)
memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload);

static void
memory_manager_init (MonoMemoryManager *memory_manager, MonoDomain *domain, gboolean collectible,
gboolean dynamic_method)
{
memory_manager->domain = domain;
memory_manager->freeing = FALSE;
memory_manager->dynamic_method = dynamic_method;

mono_coop_mutex_init_recursive (&memory_manager->lock);

memory_manager->mp = mono_mempool_new ();
if (dynamic_method)
memory_manager->mp = mono_mempool_new_size (256);
else
memory_manager->mp = mono_mempool_new ();
memory_manager->code_mp = mono_code_manager_new ();

memory_manager->class_vtable_array = g_ptr_array_new ();
if (!dynamic_method) {
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");
// 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);
memory_manager_init ((MonoMemoryManager *)mem_manager, domain, collectible, FALSE);

mem_manager->memory_manager.is_generic = FALSE;
mem_manager->alc = alc;

return mem_manager;
}

MonoMemoryManager *
mono_mem_manager_create_dynamic_method (MonoDomain *domain)
{
MonoMemoryManager *mem_manager = g_new0 (MonoMemoryManager, 1);
memory_manager_init (mem_manager, domain, FALSE, TRUE);

return mem_manager;
}

void
mono_mem_manager_free_dynamic_method (MonoMemoryManager *memory_manager)
{
memory_manager_delete (memory_manager, FALSE);
}

static void
cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
{
Expand Down Expand Up @@ -76,24 +101,27 @@ memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload)
{
// Scan here to assert no lingering references in vtables?

if (!memory_manager->freeing)
if (!memory_manager->dynamic_method && !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);
if (memory_manager->code_mp)
/* Can already be freed by the JIT */
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;
if (memory_manager->code_mp)
/* Can already be freed by the JIT */
mono_code_manager_destroy (memory_manager->code_mp);
}
g_free (memory_manager);
}

void
Expand All @@ -110,7 +138,6 @@ mono_mem_manager_free_singleton (MonoSingletonMemoryManager *memory_manager, gbo
g_assert (!memory_manager->memory_manager.is_generic);

memory_manager_delete (&memory_manager->memory_manager, debug_unload);
g_free (memory_manager);
}

void
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/metadata/method-builder-ilgen-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ struct _MonoMethodBuilder {
MonoMethod *method;
gchar *name;
gboolean no_dup_name;
gboolean dynamic;
GList *locals_list;
gint locals;
gboolean dynamic;
gboolean skip_visibility;
gboolean init_locals;
guint32 code_size;
Expand Down
8 changes: 4 additions & 4 deletions src/mono/mono/metadata/method-builder-ilgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ create_method_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int
image = m_class_get_image (mb->method->klass);

if (mb->dynamic) {
method = mb->method;
method = (MonoMethod*)g_new0 (MonoDynamicMethod, 1);
memcpy (method, mb->method, sizeof (MonoMethodWrapper));
((MonoDynamicMethod*)method)->mem_manager = mono_mem_manager_create_dynamic_method (mono_domain_get ());
mw = (MonoMethodWrapper*)method;

method->name = mb->name;
Expand All @@ -102,10 +104,8 @@ create_method_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int
for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
header->locals [i] = (MonoType*)l->data;
}
} else
{
} else {
/* Realloc the method info into a mempool */

method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
memcpy (method, mb->method, sizeof (MonoMethodWrapper));
mw = (MonoMethodWrapper*) method;
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/metadata/method-builder-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct _MonoMethodBuilder {
MonoMethod *method;
gchar *name;
gboolean no_dup_name;
gboolean dynamic;
};

#endif
23 changes: 13 additions & 10 deletions src/mono/mono/metadata/method-builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,21 @@ create_method_noilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, in

image = m_class_get_image (mb->method->klass);

{
/* Realloc the method info into a mempool */

/* Realloc the method info into a mempool */
if (mb->dynamic)
method = (MonoMethod *)g_malloc0 (sizeof (MonoDynamicMethod));
else
method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
memcpy (method, mb->method, sizeof (MonoMethodWrapper));
mw = (MonoMethodWrapper*) method;
memcpy (method, mb->method, sizeof (MonoMethodWrapper));
mw = (MonoMethodWrapper*) method;

if (mb->no_dup_name)
method->name = mb->name;
else
method->name = mono_image_strdup (image, mb->name);
}
if (mb->dynamic)
((MonoDynamicMethod*)method)->mem_manager = mono_mem_manager_create_dynamic_method (mono_domain_get ());

if (mb->no_dup_name)
method->name = mb->name;
else
method->name = mono_image_strdup (image, mb->name);

method->signature = signature;
if (!signature->hasthis)
Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/metadata/sre.c
Original file line number Diff line number Diff line change
Expand Up @@ -3038,7 +3038,8 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
else
m = (MonoMethod *)image_g_new0 (image, MonoDynamicMethod, 1);

if (dynamic)
((MonoDynamicMethod*)m)->mem_manager = mono_mem_manager_create_dynamic_method (mono_domain_get ());
wrapperm = (MonoMethodWrapper*)m;

m->dynamic = dynamic;
Expand Down
13 changes: 3 additions & 10 deletions src/mono/mono/mini/lldb.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,22 +428,15 @@ mono_lldb_save_method_info (MonoCompile *cfg)
/* Find the codegen region which contains the code */
memset (&udata, 0, sizeof (udata));
udata.code = cfg->native_code;
mono_mem_manager_code_foreach (cfg->mem_manager, find_code_region, &udata);
g_assert (udata.found);
region_id = register_codegen_region (udata.region_start, udata.region_size, cfg->method->dynamic);
if (cfg->method->dynamic) {
mono_code_manager_foreach (cfg->dynamic_info->code_mp, find_code_region, &udata);
g_assert (udata.found);

region_id = register_codegen_region (udata.region_start, udata.region_size, TRUE);

lldb_lock ();
if (!dyn_codegen_regions)
dyn_codegen_regions = g_hash_table_new (NULL, NULL);
g_hash_table_insert (dyn_codegen_regions, cfg->method, GINT_TO_POINTER (region_id));
lldb_unlock ();
} else {
mono_mem_manager_code_foreach (cfg->mem_manager, find_code_region, &udata);
g_assert (udata.found);

region_id = register_codegen_region (udata.region_start, udata.region_size, FALSE);
}

buffer_init (buf, 256);
Expand Down
24 changes: 11 additions & 13 deletions src/mono/mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1456,16 +1456,11 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
case MONO_PATCH_INFO_SWITCH: {
gpointer *jump_table;
int i;
if (method && method->dynamic) {
jump_table = (void **)mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
} else {
MonoMemoryManager *mem_manager = m_method_get_mem_manager (domain, method);
if (mono_aot_only) {
jump_table = (void **)mono_mem_manager_alloc (mem_manager, sizeof (gpointer) * patch_info->data.table->table_size);
} else {
jump_table = (void **)mono_mem_manager_code_reserve (mem_manager, sizeof (gpointer) * patch_info->data.table->table_size);
}
}
MonoMemoryManager *mem_manager = method ? m_method_get_mem_manager (domain, method) : mono_domain_memory_manager (domain);
if (mono_aot_only)
jump_table = (void **)mono_mem_manager_alloc (mem_manager, sizeof (gpointer) * patch_info->data.table->table_size);
else
jump_table = (void **)mono_mem_manager_code_reserve (mem_manager, sizeof (gpointer) * patch_info->data.table->table_size);

mono_codeman_enable_write ();
for (i = 0; i < patch_info->data.table->table_size; i++) {
Expand Down Expand Up @@ -1803,7 +1798,7 @@ mini_patch_llvm_jit_callees (MonoDomain *domain, MonoMethod *method, gpointer ad
}

void
mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
mini_init_gsctx (MonoGenericContext *context, MonoGenericSharingContext *gsctx)
{
MonoGenericInst *inst;
int i;
Expand Down Expand Up @@ -2752,6 +2747,7 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
GHashTableIter iter;
MonoJumpList *jlist;
MonoJitDomainInfo *info = domain_jit_info (domain);
MonoDynamicMethod *dmethod = (MonoDynamicMethod*)method;

g_assert (method->dynamic);

Expand Down Expand Up @@ -2824,8 +2820,11 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
*/
mono_jit_info_table_remove (domain, ji->ji);

/* Free the code manager here if needed, the mem manager will be freed in mono_free_method () */
if (destroy)
mono_code_manager_destroy (ji->code_mp);
mono_code_manager_destroy (dmethod->mem_manager->code_mp);
dmethod->mem_manager->code_mp = NULL;

g_free (ji);
}

Expand Down Expand Up @@ -4204,7 +4203,6 @@ static void
dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
{
MonoJitDynamicMethodInfo *di = (MonoJitDynamicMethodInfo *)value;
mono_code_manager_destroy (di->code_mp);
g_free (di);
}

Expand Down
Loading