12 #define USE_DL_PREFIX 1
14 #include "mono-codeman.h"
15 #include "mono-mmap.h"
17 #include <mono/metadata/class-internals.h>
18 #include <mono/metadata/profiler-private.h>
19 #ifdef HAVE_VALGRIND_MEMCHECK_H
20 #include <valgrind/memcheck.h>
24 * AMD64 processors maintain icache coherency only for pages which are
25 * marked executable. Also, windows DEP requires us to obtain executable memory from
26 * malloc when using dynamic code managers. The system malloc can't do this so we use a
27 * slighly modified version of Doug Lea's Malloc package for this purpose:
28 * http://g.oswego.edu/dl/html/malloc.html
33 #if defined(__ia64__) || defined(__x86_64__)
35 * We require 16 byte alignment on amd64 so the fp literals embedded in the code are
36 * properly aligned for SSE2.
42 #ifdef __native_client_codegen__
43 /* For Google Native Client, all targets of indirect control flow need to */
44 /* be aligned to a 32-byte boundary. MIN_ALIGN was updated to 32 to force */
45 /* alignment for calls from tramp-x86.c to mono_global_codeman_reserve() */
46 /* and mono_domain_code_reserve(). */
51 /* if a chunk has less than this amount of free space it's considered full */
52 #define MAX_WASTAGE 32
56 #define ARCH_MAP_FLAGS MONO_MMAP_32BIT
58 #define ARCH_MAP_FLAGS 0
61 #define MONO_PROT_RWX (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC)
63 typedef struct _CodeChunck CodeChunk;
75 unsigned int flags: 8;
76 /* this number of bytes is available to resolve addresses far in memory */
77 unsigned int bsize: 24;
80 struct _MonoCodeManager {
87 #define ALIGN_INT(val,alignment) (((val) + (alignment - 1)) & ~(alignment - 1))
90 * mono_code_manager_new:
92 * Creates a new code manager. A code manager can be used to allocate memory
93 * suitable for storing native code that can be later executed.
94 * A code manager allocates memory from the operating system in large chunks
95 * (typically 64KB in size) so that many methods can be allocated inside them
96 * close together, improving cache locality.
98 * Returns: the new code manager
101 mono_code_manager_new (void)
103 MonoCodeManager *cman = malloc (sizeof (MonoCodeManager));
106 cman->current = NULL;
114 * mono_code_manager_new_dynamic:
116 * Creates a new code manager suitable for holding native code that can be
117 * used for single or small methods that need to be deallocated independently
118 * of other native code.
120 * Returns: the new code manager
123 mono_code_manager_new_dynamic (void)
125 MonoCodeManager *cman = mono_code_manager_new ();
132 free_chunklist (CodeChunk *chunk)
136 #if defined(HAVE_VALGRIND_MEMCHECK_H) && defined (VALGRIND_JIT_UNREGISTER_MAP)
137 int valgrind_unregister = 0;
138 if (RUNNING_ON_VALGRIND)
139 valgrind_unregister = 1;
140 #define valgrind_unregister(x) do { if (valgrind_unregister) { VALGRIND_JIT_UNREGISTER_MAP(NULL,x); } } while (0)
142 #define valgrind_unregister(x)
147 mono_profiler_code_chunk_destroy ((gpointer) dead->data);
149 if (dead->flags == CODE_FLAG_MMAP) {
150 mono_vfree (dead->data, dead->size);
151 /* valgrind_unregister(dead->data); */
152 } else if (dead->flags == CODE_FLAG_MALLOC) {
160 * mono_code_manager_destroy:
161 * @cman: a code manager
163 * Free all the memory associated with the code manager @cman.
166 mono_code_manager_destroy (MonoCodeManager *cman)
168 free_chunklist (cman->full);
169 free_chunklist (cman->current);
174 * mono_code_manager_invalidate:
175 * @cman: a code manager
177 * Fill all the memory with an invalid native code value
178 * so that any attempt to execute code allocated in the code
179 * manager @cman will fail. This is used for debugging purposes.
182 mono_code_manager_invalidate (MonoCodeManager *cman)
186 #if defined(__i386__) || defined(__x86_64__)
187 int fill_value = 0xcc; /* x86 break */
189 int fill_value = 0x2a;
192 for (chunk = cman->current; chunk; chunk = chunk->next)
193 memset (chunk->data, fill_value, chunk->size);
194 for (chunk = cman->full; chunk; chunk = chunk->next)
195 memset (chunk->data, fill_value, chunk->size);
199 * mono_code_manager_set_read_only:
200 * @cman: a code manager
202 * Make the code manager read only, so further allocation requests cause an assert.
205 mono_code_manager_set_read_only (MonoCodeManager *cman)
207 cman->read_only = TRUE;
211 * mono_code_manager_foreach:
212 * @cman: a code manager
213 * @func: a callback function pointer
214 * @user_data: additional data to pass to @func
216 * Invokes the callback @func for each different chunk of memory allocated
217 * in the code manager @cman.
220 mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void *user_data)
223 for (chunk = cman->current; chunk; chunk = chunk->next) {
224 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
227 for (chunk = cman->full; chunk; chunk = chunk->next) {
228 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
233 /* BIND_ROOM is the divisor for the chunck of code size dedicated
234 * to binding branches (branches not reachable with the immediate displacement)
235 * bind_size = size/BIND_ROOM;
236 * we should reduce it and make MIN_PAGES bigger for such systems
238 #if defined(__ppc__) || defined(__powerpc__)
246 new_codechunk (int dynamic, int size)
248 int minsize, flags = CODE_FLAG_MMAP;
249 int chunk_size, bsize = 0;
255 flags = CODE_FLAG_MALLOC;
258 pagesize = mono_pagesize ();
262 flags = CODE_FLAG_MALLOC;
264 minsize = pagesize * MIN_PAGES;
266 chunk_size = minsize;
269 chunk_size += pagesize - 1;
270 chunk_size &= ~ (pagesize - 1);
274 bsize = chunk_size / BIND_ROOM;
275 if (bsize < MIN_BSIZE)
277 bsize += MIN_ALIGN -1;
278 bsize &= ~ (MIN_ALIGN - 1);
279 if (chunk_size - size < bsize) {
280 chunk_size = size + bsize;
281 chunk_size += pagesize - 1;
282 chunk_size &= ~ (pagesize - 1);
286 if (flags == CODE_FLAG_MALLOC) {
287 ptr = dlmemalign (MIN_ALIGN, chunk_size + MIN_ALIGN - 1);
291 ptr = mono_valloc (NULL, chunk_size, MONO_PROT_RWX | ARCH_MAP_FLAGS);
296 if (flags == CODE_FLAG_MALLOC) {
298 /* Make sure the thunks area is zeroed */
299 memset (ptr, 0, bsize);
303 chunk = malloc (sizeof (CodeChunk));
305 if (flags == CODE_FLAG_MALLOC)
308 mono_vfree (ptr, chunk_size);
312 chunk->size = chunk_size;
314 chunk->flags = flags;
316 chunk->bsize = bsize;
317 mono_profiler_code_chunk_new((gpointer) chunk->data, chunk->size);
319 /*printf ("code chunk at: %p\n", ptr);*/
324 * mono_code_manager_reserve:
325 * @cman: a code manager
326 * @size: size of memory to allocate
327 * @alignment: power of two alignment value
329 * Allocates at least @size bytes of memory inside the code manager @cman.
331 * Returns: the pointer to the allocated memory or #NULL on failure
334 mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment)
336 CodeChunk *chunk, *prev;
339 g_assert (!cman->read_only);
341 /* eventually allow bigger alignments, but we need to fix the dynamic alloc code to
344 g_assert (alignment <= MIN_ALIGN);
347 ++mono_stats.dynamic_code_alloc_count;
348 mono_stats.dynamic_code_bytes_count += size;
351 if (!cman->current) {
352 cman->current = new_codechunk (cman->dynamic, size);
357 for (chunk = cman->current; chunk; chunk = chunk->next) {
358 if (ALIGN_INT (chunk->pos, alignment) + size <= chunk->size) {
359 chunk->pos = ALIGN_INT (chunk->pos, alignment);
360 ptr = chunk->data + chunk->pos;
366 * no room found, move one filled chunk to cman->full
367 * to keep cman->current from growing too much
370 for (chunk = cman->current; chunk; prev = chunk, chunk = chunk->next) {
371 if (chunk->pos + MIN_ALIGN * 4 <= chunk->size)
374 prev->next = chunk->next;
376 cman->current = chunk->next;
378 chunk->next = cman->full;
382 chunk = new_codechunk (cman->dynamic, size);
385 chunk->next = cman->current;
386 cman->current = chunk;
387 chunk->pos = ALIGN_INT (chunk->pos, alignment);
388 ptr = chunk->data + chunk->pos;
394 * mono_code_manager_reserve:
395 * @cman: a code manager
396 * @size: size of memory to allocate
398 * Allocates at least @size bytes of memory inside the code manager @cman.
400 * Returns: the pointer to the allocated memory or #NULL on failure
403 mono_code_manager_reserve (MonoCodeManager *cman, int size)
405 return mono_code_manager_reserve_align (cman, size, MIN_ALIGN);
409 * mono_code_manager_commit:
410 * @cman: a code manager
411 * @data: the pointer returned by mono_code_manager_reserve ()
412 * @size: the size requested in the call to mono_code_manager_reserve ()
413 * @newsize: the new size to reserve
415 * If we reserved too much room for a method and we didn't allocate
416 * already from the code manager, we can get back the excess allocation
417 * for later use in the code manager.
420 mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsize)
422 g_assert (newsize <= size);
424 if (cman->current && (size != newsize) && (data == cman->current->data + cman->current->pos - size)) {
425 cman->current->pos -= size - newsize;
430 * mono_code_manager_size:
431 * @cman: a code manager
432 * @used_size: pointer to an integer for the result
434 * This function can be used to get statistics about a code manager:
435 * the integer pointed to by @used_size will contain how much
436 * memory is actually used inside the code managed @cman.
438 * Returns: the amount of memory allocated in @cman
441 mono_code_manager_size (MonoCodeManager *cman, int *used_size)
446 for (chunk = cman->current; chunk; chunk = chunk->next) {
450 for (chunk = cman->full; chunk; chunk = chunk->next) {