Apply changes from https://github.com/dotnet/runtime/commit/eb1756e97d23df13bc6fe798e...
[mono-project.git] / mono / metadata / memory-manager.c
blobf61cb422a7bba3171d005b02208a87893b4b19da
1 #include <mono/metadata/loader-internals.h>
2 #include <mono/metadata/gc-internals.h>
3 #include <mono/metadata/reflection-cache.h>
4 #include <mono/metadata/mono-hash-internals.h>
6 static void
7 memory_manager_init (MonoMemoryManager *memory_manager, MonoDomain *domain, gboolean collectible)
9 memory_manager->domain = domain;
10 memory_manager->freeing = FALSE;
12 mono_coop_mutex_init_recursive (&memory_manager->lock);
14 memory_manager->mp = mono_mempool_new ();
15 memory_manager->code_mp = mono_code_manager_new ();
17 memory_manager->class_vtable_array = g_ptr_array_new ();
19 // TODO: make these not linked to the domain for debugging
20 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");
21 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");
22 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");
25 MonoSingletonMemoryManager *
26 mono_mem_manager_create_singleton (MonoAssemblyLoadContext *alc, MonoDomain *domain, gboolean collectible)
28 MonoSingletonMemoryManager *mem_manager = g_new0 (MonoSingletonMemoryManager, 1);
29 memory_manager_init ((MonoMemoryManager *)mem_manager, domain, collectible);
31 mem_manager->memory_manager.is_generic = FALSE;
32 mem_manager->alc = alc;
34 return mem_manager;
37 static void
38 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
40 free_reflected_entry ((ReflectedEntry *)key);
43 static void
44 unregister_vtable_reflection_type (MonoVTable *vtable)
46 MonoObject *type = (MonoObject *)vtable->type;
48 if (type->vtable->klass != mono_defaults.runtimetype_class)
49 MONO_GC_UNREGISTER_ROOT_IF_MOVING (vtable->type);
52 // First phase of deletion
53 static void
54 memory_manager_delete_objects (MonoMemoryManager *memory_manager)
56 memory_manager->freeing = TRUE;
58 // Must be done before type_hash is freed
59 for (int i = 0; i < memory_manager->class_vtable_array->len; i++)
60 unregister_vtable_reflection_type ((MonoVTable *)g_ptr_array_index (memory_manager->class_vtable_array, i));
62 g_ptr_array_free (memory_manager->class_vtable_array, TRUE);
63 memory_manager->class_vtable_array = NULL;
64 mono_g_hash_table_destroy (memory_manager->type_hash);
65 memory_manager->type_hash = NULL;
66 mono_conc_g_hash_table_foreach (memory_manager->refobject_hash, cleanup_refobject_hash, NULL);
67 mono_conc_g_hash_table_destroy (memory_manager->refobject_hash);
68 memory_manager->refobject_hash = NULL;
69 mono_g_hash_table_destroy (memory_manager->type_init_exception_hash);
70 memory_manager->type_init_exception_hash = NULL;
73 // Full deletion
74 static void
75 memory_manager_delete (MonoMemoryManager *memory_manager, gboolean debug_unload)
77 // Scan here to assert no lingering references in vtables?
79 if (!memory_manager->freeing)
80 memory_manager_delete_objects (memory_manager);
82 mono_coop_mutex_destroy (&memory_manager->lock);
84 if (debug_unload) {
85 mono_mempool_invalidate (memory_manager->mp);
86 mono_code_manager_invalidate (memory_manager->code_mp);
87 } else {
88 #ifndef DISABLE_PERFCOUNTERS
89 /* FIXME: use an explicit subtraction method as soon as it's available */
90 mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, -1 * mono_mempool_get_allocated (memory_manager->mp));
91 #endif
92 mono_mempool_destroy (memory_manager->mp);
93 memory_manager->mp = NULL;
94 mono_code_manager_destroy (memory_manager->code_mp);
95 memory_manager->code_mp = NULL;
99 void
100 mono_mem_manager_free_objects_singleton (MonoSingletonMemoryManager *memory_manager)
102 g_assert (!memory_manager->memory_manager.freeing);
104 memory_manager_delete_objects (&memory_manager->memory_manager);
107 void
108 mono_mem_manager_free_singleton (MonoSingletonMemoryManager *memory_manager, gboolean debug_unload)
110 g_assert (!memory_manager->memory_manager.is_generic);
112 memory_manager_delete (&memory_manager->memory_manager, debug_unload);
113 g_free (memory_manager);
116 void
117 mono_mem_manager_lock (MonoMemoryManager *memory_manager)
119 //mono_coop_mutex_lock (&memory_manager->lock);
120 mono_domain_lock (memory_manager->domain);
123 void
124 mono_mem_manager_unlock (MonoMemoryManager *memory_manager)
126 //mono_coop_mutex_unlock (&memory_manager->lock);
127 mono_domain_unlock (memory_manager->domain);
130 void *
131 mono_mem_manager_alloc (MonoMemoryManager *memory_manager, guint size)
133 void *res;
135 mono_mem_manager_lock (memory_manager);
136 res = mono_mem_manager_alloc_nolock (memory_manager, size);
137 mono_mem_manager_unlock (memory_manager);
139 return res;
142 void *
143 mono_mem_manager_alloc_nolock (MonoMemoryManager *memory_manager, guint size)
145 #ifndef DISABLE_PERFCOUNTERS
146 mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, size);
147 #endif
148 return mono_mempool_alloc (memory_manager->mp, size);
151 void *
152 mono_mem_manager_alloc0 (MonoMemoryManager *memory_manager, guint size)
154 void *res;
156 mono_mem_manager_lock (memory_manager);
157 res = mono_mem_manager_alloc0_nolock (memory_manager, size);
158 mono_mem_manager_unlock (memory_manager);
160 return res;
163 void *
164 mono_mem_manager_alloc0_nolock (MonoMemoryManager *memory_manager, guint size)
166 #ifndef DISABLE_PERFCOUNTERS
167 mono_atomic_fetch_add_i32 (&mono_perfcounters->loader_bytes, size);
168 #endif
169 return mono_mempool_alloc0 (memory_manager->mp, size);
172 char*
173 mono_mem_manager_strdup (MonoMemoryManager *memory_manager, const char *s)
175 char *res;
177 mono_mem_manager_lock (memory_manager);
178 res = mono_mempool_strdup (memory_manager->mp, s);
179 mono_mem_manager_unlock (memory_manager);
181 return res;
184 void *
185 (mono_mem_manager_code_reserve) (MonoMemoryManager *memory_manager, int size)
187 void *res;
189 mono_mem_manager_lock (memory_manager);
190 res = mono_code_manager_reserve (memory_manager->code_mp, size);
191 mono_mem_manager_unlock (memory_manager);
193 return res;
196 void *
197 mono_mem_manager_code_reserve_align (MonoMemoryManager *memory_manager, int size, int alignment)
199 void *res;
201 mono_mem_manager_lock (memory_manager);
202 res = mono_code_manager_reserve_align (memory_manager->code_mp, size, alignment);
203 mono_mem_manager_unlock (memory_manager);
205 return res;
208 void
209 mono_mem_manager_code_commit (MonoMemoryManager *memory_manager, void *data, int size, int newsize)
211 mono_mem_manager_lock (memory_manager);
212 mono_code_manager_commit (memory_manager->code_mp, data, size, newsize);
213 mono_mem_manager_unlock (memory_manager);
217 * mono_mem_manager_code_foreach:
218 * Iterate over the code thunks of the code manager of @memory_manager.
220 * The @func callback MUST not take any locks. If it really needs to, it must respect
221 * the locking rules of the runtime: http://www.mono-project.com/Mono:Runtime:Documentation:ThreadSafety
222 * LOCKING: Acquires the memory manager lock.
224 void
225 mono_mem_manager_code_foreach (MonoMemoryManager *memory_manager, MonoCodeManagerFunc func, void *user_data)
227 mono_mem_manager_lock (memory_manager);
228 mono_code_manager_foreach (memory_manager->code_mp, func, user_data);
229 mono_mem_manager_unlock (memory_manager);