Merge pull request #631 from kebby/master
[mono.git] / mono / utils / mono-codeman.c
1 #include "config.h"
2
3 #ifdef HAVE_UNISTD_H
4 #include <unistd.h>
5 #endif
6 #include <stdlib.h>
7 #include <string.h>
8 #include <assert.h>
9 #include <glib.h>
10
11 /* For dlmalloc.h */
12 #define USE_DL_PREFIX 1
13
14 #include "mono-codeman.h"
15 #include "mono-mmap.h"
16 #include "mono-counters.h"
17 #include "dlmalloc.h"
18 #include <mono/metadata/class-internals.h>
19 #include <mono/metadata/profiler-private.h>
20 #ifdef HAVE_VALGRIND_MEMCHECK_H
21 #include <valgrind/memcheck.h>
22 #endif
23
24 #if defined(__native_client_codegen__) && defined(__native_client__)
25 #include <malloc.h>
26 #include <nacl/nacl_dyncode.h>
27 #include <mono/mini/mini.h>
28 #endif
29
30 static uintptr_t code_memory_used = 0;
31
32 /*
33  * AMD64 processors maintain icache coherency only for pages which are 
34  * marked executable. Also, windows DEP requires us to obtain executable memory from
35  * malloc when using dynamic code managers. The system malloc can't do this so we use a 
36  * slighly modified version of Doug Lea's Malloc package for this purpose:
37  * http://g.oswego.edu/dl/html/malloc.html
38  */
39
40 #define MIN_PAGES 16
41
42 #if defined(__ia64__) || defined(__x86_64__)
43 /*
44  * We require 16 byte alignment on amd64 so the fp literals embedded in the code are 
45  * properly aligned for SSE2.
46  */
47 #define MIN_ALIGN 16
48 #else
49 #define MIN_ALIGN 8
50 #endif
51 #ifdef __native_client_codegen__
52 /* For Google Native Client, all targets of indirect control flow need to    */
53 /* be aligned to bundle boundary. 16 bytes on ARM, 32 bytes on x86.
54  * MIN_ALIGN was updated to force alignment for calls from
55  * tramp-<arch>.c to mono_global_codeman_reserve()     */
56 /* and mono_domain_code_reserve().                                           */
57 #undef MIN_ALIGN
58 #define MIN_ALIGN kNaClBundleSize
59
60 #endif
61
62 /* if a chunk has less than this amount of free space it's considered full */
63 #define MAX_WASTAGE 32
64 #define MIN_BSIZE 32
65
66 #ifdef __x86_64__
67 #define ARCH_MAP_FLAGS MONO_MMAP_32BIT
68 #else
69 #define ARCH_MAP_FLAGS 0
70 #endif
71
72 #define MONO_PROT_RWX (MONO_MMAP_READ|MONO_MMAP_WRITE|MONO_MMAP_EXEC)
73
74 typedef struct _CodeChunck CodeChunk;
75
76 enum {
77         CODE_FLAG_MMAP,
78         CODE_FLAG_MALLOC
79 };
80
81 struct _CodeChunck {
82         char *data;
83         int pos;
84         int size;
85         CodeChunk *next;
86         unsigned int flags: 8;
87         /* this number of bytes is available to resolve addresses far in memory */
88         unsigned int bsize: 24;
89 };
90
91 struct _MonoCodeManager {
92         int dynamic;
93         int read_only;
94         CodeChunk *current;
95         CodeChunk *full;
96 #if defined(__native_client_codegen__) && defined(__native_client__)
97         GHashTable *hash;
98 #endif
99 };
100
101 #define ALIGN_INT(val,alignment) (((val) + (alignment - 1)) & ~(alignment - 1))
102
103 #if defined(__native_client_codegen__) && defined(__native_client__)
104 /* End of text segment, set by linker. 
105  * Dynamic text starts on the next allocated page.
106  */
107 extern char etext[];
108 char *next_dynamic_code_addr = NULL;
109
110 /*
111  * This routine gets the next available bundle aligned
112  * pointer in the dynamic code section.  It does not check
113  * for the section end, this error will be caught in the
114  * service runtime.
115  */
116 void*
117 allocate_code(intptr_t increment)
118 {
119         char *addr;
120         if (increment < 0) return NULL;
121         increment = increment & kNaClBundleMask ? (increment & ~kNaClBundleMask) + kNaClBundleSize : increment;
122         addr = next_dynamic_code_addr;
123         next_dynamic_code_addr += increment;
124         return addr;
125 }
126
127 int
128 nacl_is_code_address (void *target)
129 {
130         return (char *)target < next_dynamic_code_addr;
131 }
132
133 /* Fill code buffer with arch-specific NOPs. */
134 void
135 mono_nacl_fill_code_buffer (guint8 *data, int size);
136
137 #ifndef USE_JUMP_TABLES
138 const int kMaxPatchDepth = 32;
139 __thread unsigned char **patch_source_base = NULL;
140 __thread unsigned char **patch_dest_base = NULL;
141 __thread int *patch_alloc_size = NULL;
142 __thread int patch_current_depth = -1;
143 __thread int allow_target_modification = 1;
144
145 static void
146 nacl_jit_check_init ()
147 {
148         if (patch_source_base == NULL) {
149                 patch_source_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
150                 patch_dest_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
151                 patch_alloc_size = g_malloc (kMaxPatchDepth * sizeof(int));
152         }
153 }
154 #endif
155
156 void
157 nacl_allow_target_modification (int val)
158 {
159 #ifndef USE_JUMP_TABLES
160         allow_target_modification = val;
161 #endif /* USE_JUMP_TABLES */
162 }
163
164 /* Given a patch target, modify the target such that patching will work when
165  * the code is copied to the data section.
166  */
167 void*
168 nacl_modify_patch_target (unsigned char *target)
169 {
170         /*
171          * There's no need in patch tricks for jumptables,
172          * as we always patch same jumptable.
173          */
174 #ifndef USE_JUMP_TABLES
175         /* This seems like a bit of an ugly way to do this but the advantage
176          * is we don't have to worry about all the conditions in
177          * mono_resolve_patch_target, and it can be used by all the bare uses
178          * of <arch>_patch.
179          */
180         unsigned char *sb;
181         unsigned char *db;
182
183         if (!allow_target_modification) return target;
184
185         nacl_jit_check_init ();
186         sb = patch_source_base[patch_current_depth];
187         db = patch_dest_base[patch_current_depth];
188
189         if (target >= sb && (target < sb + patch_alloc_size[patch_current_depth])) {
190                 /* Do nothing.  target is in the section being generated.
191                  * no need to modify, the disp will be the same either way.
192                  */
193         } else {
194                 int target_offset = target - db;
195                 target = sb + target_offset;
196         }
197 #endif
198         return target;
199 }
200
201 void*
202 nacl_inverse_modify_patch_target (unsigned char *target)
203 {
204         /*
205          * There's no need in patch tricks for jumptables,
206          * as we always patch same jumptable.
207          */
208 #ifndef USE_JUMP_TABLES
209         unsigned char *sb;
210         unsigned char *db;
211         int target_offset;
212
213         if (!allow_target_modification) return target;
214
215         nacl_jit_check_init ();
216         sb = patch_source_base[patch_current_depth];
217         db = patch_dest_base[patch_current_depth];
218
219         target_offset = target - sb;
220         target = db + target_offset;
221 #endif
222         return target;
223 }
224
225
226 #endif /* __native_client_codegen && __native_client__ */
227
228 #define VALLOC_FREELIST_SIZE 16
229
230 static CRITICAL_SECTION valloc_mutex;
231 static GHashTable *valloc_freelists;
232
233 static void*
234 codechunk_valloc (guint32 size)
235 {
236         void *ptr;
237         GSList *freelist;
238
239         if (!valloc_freelists) {
240                 InitializeCriticalSection (&valloc_mutex);
241                 valloc_freelists = g_hash_table_new (NULL, NULL);
242         }
243
244         /*
245          * Keep a small freelist of memory blocks to decrease pressure on the kernel memory subsystem to avoid #3321.
246          */
247         EnterCriticalSection (&valloc_mutex);
248         freelist = g_hash_table_lookup (valloc_freelists, GUINT_TO_POINTER (size));
249         if (freelist) {
250                 ptr = freelist->data;
251                 memset (ptr, 0, size);
252                 freelist = g_slist_remove_link (freelist, freelist);
253                 g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
254         } else {
255                 ptr = mono_valloc (NULL, size + MIN_ALIGN - 1, MONO_PROT_RWX | ARCH_MAP_FLAGS);
256         }
257         LeaveCriticalSection (&valloc_mutex);
258         return ptr;
259 }
260
261 static void
262 codechunk_vfree (void *ptr, guint32 size)
263 {
264         GSList *freelist;
265
266         EnterCriticalSection (&valloc_mutex);
267         freelist = g_hash_table_lookup (valloc_freelists, GUINT_TO_POINTER (size));
268         if (!freelist || g_slist_length (freelist) < VALLOC_FREELIST_SIZE) {
269                 freelist = g_slist_prepend (freelist, ptr);
270                 g_hash_table_insert (valloc_freelists, GUINT_TO_POINTER (size), freelist);
271         } else {
272                 mono_vfree (ptr, size);
273         }
274         LeaveCriticalSection (&valloc_mutex);
275 }               
276
277 static void
278 codechunk_cleanup (void)
279 {
280         GHashTableIter iter;
281         gpointer key, value;
282
283         if (!valloc_freelists)
284                 return;
285         g_hash_table_iter_init (&iter, valloc_freelists);
286         while (g_hash_table_iter_next (&iter, &key, &value)) {
287                 GSList *freelist = value;
288                 GSList *l;
289
290                 for (l = freelist; l; l = l->next) {
291                         mono_vfree (l->data, GPOINTER_TO_UINT (key));
292                 }
293                 g_slist_free (freelist);
294         }
295         g_hash_table_destroy (valloc_freelists);
296 }
297
298 void
299 mono_code_manager_init (void)
300 {
301 }
302
303 void
304 mono_code_manager_cleanup (void)
305 {
306         codechunk_cleanup ();
307 }
308
309 /**
310  * mono_code_manager_new:
311  *
312  * Creates a new code manager. A code manager can be used to allocate memory
313  * suitable for storing native code that can be later executed.
314  * A code manager allocates memory from the operating system in large chunks
315  * (typically 64KB in size) so that many methods can be allocated inside them
316  * close together, improving cache locality.
317  *
318  * Returns: the new code manager
319  */
320 MonoCodeManager* 
321 mono_code_manager_new (void)
322 {
323         MonoCodeManager *cman = malloc (sizeof (MonoCodeManager));
324         if (!cman)
325                 return NULL;
326         cman->current = NULL;
327         cman->full = NULL;
328         cman->dynamic = 0;
329         cman->read_only = 0;
330 #if defined(__native_client_codegen__) && defined(__native_client__)
331         if (next_dynamic_code_addr == NULL) {
332                 const guint kPageMask = 0xFFFF; /* 64K pages */
333                 next_dynamic_code_addr = (uintptr_t)(etext + kPageMask) & ~kPageMask;
334 #if defined (__GLIBC__)
335                 /* TODO: For now, just jump 64MB ahead to avoid dynamic libraries. */
336                 next_dynamic_code_addr += (uintptr_t)0x4000000;
337 #else
338                 /* Workaround bug in service runtime, unable to allocate */
339                 /* from the first page in the dynamic code section.    */
340                 next_dynamic_code_addr += (uintptr_t)0x10000;
341 #endif
342         }
343         cman->hash =  g_hash_table_new (NULL, NULL);
344 # ifndef USE_JUMP_TABLES
345         if (patch_source_base == NULL) {
346                 patch_source_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
347                 patch_dest_base = g_malloc (kMaxPatchDepth * sizeof(unsigned char *));
348                 patch_alloc_size = g_malloc (kMaxPatchDepth * sizeof(int));
349         }
350 # endif
351 #endif
352         return cman;
353 }
354
355 /**
356  * mono_code_manager_new_dynamic:
357  *
358  * Creates a new code manager suitable for holding native code that can be
359  * used for single or small methods that need to be deallocated independently
360  * of other native code.
361  *
362  * Returns: the new code manager
363  */
364 MonoCodeManager* 
365 mono_code_manager_new_dynamic (void)
366 {
367         MonoCodeManager *cman = mono_code_manager_new ();
368         cman->dynamic = 1;
369         return cman;
370 }
371
372
373 static void
374 free_chunklist (CodeChunk *chunk)
375 {
376         CodeChunk *dead;
377         
378 #if defined(HAVE_VALGRIND_MEMCHECK_H) && defined (VALGRIND_JIT_UNREGISTER_MAP)
379         int valgrind_unregister = 0;
380         if (RUNNING_ON_VALGRIND)
381                 valgrind_unregister = 1;
382 #define valgrind_unregister(x) do { if (valgrind_unregister) { VALGRIND_JIT_UNREGISTER_MAP(NULL,x); } } while (0) 
383 #else
384 #define valgrind_unregister(x)
385 #endif
386
387         for (; chunk; ) {
388                 dead = chunk;
389                 mono_profiler_code_chunk_destroy ((gpointer) dead->data);
390                 chunk = chunk->next;
391                 if (dead->flags == CODE_FLAG_MMAP) {
392                         codechunk_vfree (dead->data, dead->size);
393                         /* valgrind_unregister(dead->data); */
394                 } else if (dead->flags == CODE_FLAG_MALLOC) {
395                         dlfree (dead->data);
396                 }
397                 code_memory_used -= dead->size;
398                 free (dead);
399         }
400 }
401
402 /**
403  * mono_code_manager_destroy:
404  * @cman: a code manager
405  *
406  * Free all the memory associated with the code manager @cman.
407  */
408 void
409 mono_code_manager_destroy (MonoCodeManager *cman)
410 {
411         free_chunklist (cman->full);
412         free_chunklist (cman->current);
413         free (cman);
414 }
415
416 /**
417  * mono_code_manager_invalidate:
418  * @cman: a code manager
419  *
420  * Fill all the memory with an invalid native code value
421  * so that any attempt to execute code allocated in the code
422  * manager @cman will fail. This is used for debugging purposes.
423  */
424 void             
425 mono_code_manager_invalidate (MonoCodeManager *cman)
426 {
427         CodeChunk *chunk;
428
429 #if defined(__i386__) || defined(__x86_64__)
430         int fill_value = 0xcc; /* x86 break */
431 #else
432         int fill_value = 0x2a;
433 #endif
434
435         for (chunk = cman->current; chunk; chunk = chunk->next)
436                 memset (chunk->data, fill_value, chunk->size);
437         for (chunk = cman->full; chunk; chunk = chunk->next)
438                 memset (chunk->data, fill_value, chunk->size);
439 }
440
441 /**
442  * mono_code_manager_set_read_only:
443  * @cman: a code manager
444  *
445  * Make the code manager read only, so further allocation requests cause an assert.
446  */
447 void             
448 mono_code_manager_set_read_only (MonoCodeManager *cman)
449 {
450         cman->read_only = TRUE;
451 }
452
453 /**
454  * mono_code_manager_foreach:
455  * @cman: a code manager
456  * @func: a callback function pointer
457  * @user_data: additional data to pass to @func
458  *
459  * Invokes the callback @func for each different chunk of memory allocated
460  * in the code manager @cman.
461  */
462 void
463 mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void *user_data)
464 {
465         CodeChunk *chunk;
466         for (chunk = cman->current; chunk; chunk = chunk->next) {
467                 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
468                         return;
469         }
470         for (chunk = cman->full; chunk; chunk = chunk->next) {
471                 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
472                         return;
473         }
474 }
475
476 /* BIND_ROOM is the divisor for the chunck of code size dedicated
477  * to binding branches (branches not reachable with the immediate displacement)
478  * bind_size = size/BIND_ROOM;
479  * we should reduce it and make MIN_PAGES bigger for such systems
480  */
481 #if defined(__ppc__) || defined(__powerpc__)
482 #define BIND_ROOM 4
483 #endif
484 #if defined(__arm__)
485 #define BIND_ROOM 8
486 #endif
487
488 static CodeChunk*
489 new_codechunk (int dynamic, int size)
490 {
491         int minsize, flags = CODE_FLAG_MMAP;
492         int chunk_size, bsize = 0;
493         int pagesize;
494         CodeChunk *chunk;
495         void *ptr;
496
497 #ifdef FORCE_MALLOC
498         flags = CODE_FLAG_MALLOC;
499 #endif
500
501         pagesize = mono_pagesize ();
502
503         if (dynamic) {
504                 chunk_size = size;
505                 flags = CODE_FLAG_MALLOC;
506         } else {
507                 minsize = pagesize * MIN_PAGES;
508                 if (size < minsize)
509                         chunk_size = minsize;
510                 else {
511                         chunk_size = size;
512                         chunk_size += pagesize - 1;
513                         chunk_size &= ~ (pagesize - 1);
514                 }
515         }
516 #ifdef BIND_ROOM
517         bsize = chunk_size / BIND_ROOM;
518         if (bsize < MIN_BSIZE)
519                 bsize = MIN_BSIZE;
520         bsize += MIN_ALIGN -1;
521         bsize &= ~ (MIN_ALIGN - 1);
522         if (chunk_size - size < bsize) {
523                 chunk_size = size + bsize;
524                 chunk_size += pagesize - 1;
525                 chunk_size &= ~ (pagesize - 1);
526         }
527 #endif
528
529         if (flags == CODE_FLAG_MALLOC) {
530                 ptr = dlmemalign (MIN_ALIGN, chunk_size + MIN_ALIGN - 1);
531                 if (!ptr)
532                         return NULL;
533         } else {
534                 /* Allocate MIN_ALIGN-1 more than we need so we can still */
535                 /* guarantee MIN_ALIGN alignment for individual allocs    */
536                 /* from mono_code_manager_reserve_align.                  */
537                 ptr = codechunk_valloc (chunk_size);
538                 if (!ptr)
539                         return NULL;
540         }
541
542         if (flags == CODE_FLAG_MALLOC) {
543 #ifdef BIND_ROOM
544                 /* Make sure the thunks area is zeroed */
545                 memset (ptr, 0, bsize);
546 #endif
547         }
548
549         chunk = malloc (sizeof (CodeChunk));
550         if (!chunk) {
551                 if (flags == CODE_FLAG_MALLOC)
552                         dlfree (ptr);
553                 else
554                         mono_vfree (ptr, chunk_size);
555                 return NULL;
556         }
557         chunk->next = NULL;
558         chunk->size = chunk_size;
559         chunk->data = ptr;
560         chunk->flags = flags;
561         chunk->pos = bsize;
562         chunk->bsize = bsize;
563         mono_profiler_code_chunk_new((gpointer) chunk->data, chunk->size);
564
565         code_memory_used += chunk_size;
566         mono_runtime_resource_check_limit (MONO_RESOURCE_JIT_CODE, code_memory_used);
567         /*printf ("code chunk at: %p\n", ptr);*/
568         return chunk;
569 }
570
571 /**
572  * mono_code_manager_reserve:
573  * @cman: a code manager
574  * @size: size of memory to allocate
575  * @alignment: power of two alignment value
576  *
577  * Allocates at least @size bytes of memory inside the code manager @cman.
578  *
579  * Returns: the pointer to the allocated memory or #NULL on failure
580  */
581 void*
582 mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment)
583 {
584 #if !defined(__native_client__) || !defined(__native_client_codegen__)
585         CodeChunk *chunk, *prev;
586         void *ptr;
587         guint32 align_mask = alignment - 1;
588
589         g_assert (!cman->read_only);
590
591         /* eventually allow bigger alignments, but we need to fix the dynamic alloc code to
592          * handle this before
593          */
594         g_assert (alignment <= MIN_ALIGN);
595
596         if (cman->dynamic) {
597                 ++mono_stats.dynamic_code_alloc_count;
598                 mono_stats.dynamic_code_bytes_count += size;
599         }
600
601         if (!cman->current) {
602                 cman->current = new_codechunk (cman->dynamic, size);
603                 if (!cman->current)
604                         return NULL;
605         }
606
607         for (chunk = cman->current; chunk; chunk = chunk->next) {
608                 if (ALIGN_INT (chunk->pos, alignment) + size <= chunk->size) {
609                         chunk->pos = ALIGN_INT (chunk->pos, alignment);
610                         /* Align the chunk->data we add to chunk->pos */
611                         /* or we can't guarantee proper alignment     */
612                         ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos);
613                         chunk->pos = ((char*)ptr - chunk->data) + size;
614                         return ptr;
615                 }
616         }
617         /* 
618          * no room found, move one filled chunk to cman->full 
619          * to keep cman->current from growing too much
620          */
621         prev = NULL;
622         for (chunk = cman->current; chunk; prev = chunk, chunk = chunk->next) {
623                 if (chunk->pos + MIN_ALIGN * 4 <= chunk->size)
624                         continue;
625                 if (prev) {
626                         prev->next = chunk->next;
627                 } else {
628                         cman->current = chunk->next;
629                 }
630                 chunk->next = cman->full;
631                 cman->full = chunk;
632                 break;
633         }
634         chunk = new_codechunk (cman->dynamic, size);
635         if (!chunk)
636                 return NULL;
637         chunk->next = cman->current;
638         cman->current = chunk;
639         chunk->pos = ALIGN_INT (chunk->pos, alignment);
640         /* Align the chunk->data we add to chunk->pos */
641         /* or we can't guarantee proper alignment     */
642         ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos);
643         chunk->pos = ((char*)ptr - chunk->data) + size;
644         return ptr;
645 #else
646         unsigned char *temp_ptr, *code_ptr;
647         /* Round up size to next bundle */
648         alignment = kNaClBundleSize;
649         size = (size + kNaClBundleSize) & (~kNaClBundleMask);
650         /* Allocate a temp buffer */
651         temp_ptr = memalign (alignment, size);
652         g_assert (((uintptr_t)temp_ptr & kNaClBundleMask) == 0);
653         /* Allocate code space from the service runtime */
654         code_ptr = allocate_code (size);
655         /* Insert pointer to code space in hash, keyed by buffer ptr */
656         g_hash_table_insert (cman->hash, temp_ptr, code_ptr);
657
658 #ifndef USE_JUMP_TABLES
659         nacl_jit_check_init ();
660
661         patch_current_depth++;
662         patch_source_base[patch_current_depth] = temp_ptr;
663         patch_dest_base[patch_current_depth] = code_ptr;
664         patch_alloc_size[patch_current_depth] = size;
665         g_assert (patch_current_depth < kMaxPatchDepth);
666 #endif
667
668         return temp_ptr;
669 #endif
670 }
671
672 /**
673  * mono_code_manager_reserve:
674  * @cman: a code manager
675  * @size: size of memory to allocate
676  *
677  * Allocates at least @size bytes of memory inside the code manager @cman.
678  *
679  * Returns: the pointer to the allocated memory or #NULL on failure
680  */
681 void*
682 mono_code_manager_reserve (MonoCodeManager *cman, int size)
683 {
684         return mono_code_manager_reserve_align (cman, size, MIN_ALIGN);
685 }
686
687 /**
688  * mono_code_manager_commit:
689  * @cman: a code manager
690  * @data: the pointer returned by mono_code_manager_reserve ()
691  * @size: the size requested in the call to mono_code_manager_reserve ()
692  * @newsize: the new size to reserve
693  *
694  * If we reserved too much room for a method and we didn't allocate
695  * already from the code manager, we can get back the excess allocation
696  * for later use in the code manager.
697  */
698 void
699 mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsize)
700 {
701 #if !defined(__native_client__) || !defined(__native_client_codegen__)
702         g_assert (newsize <= size);
703
704         if (cman->current && (size != newsize) && (data == cman->current->data + cman->current->pos - size)) {
705                 cman->current->pos -= size - newsize;
706         }
707 #else
708         unsigned char *code;
709         int status;
710         g_assert (NACL_BUNDLE_ALIGN_UP(newsize) <= size);
711         code = g_hash_table_lookup (cman->hash, data);
712         g_assert (code != NULL);
713         mono_nacl_fill_code_buffer ((uint8_t*)data + newsize, size - newsize);
714         newsize = NACL_BUNDLE_ALIGN_UP(newsize);
715         g_assert ((GPOINTER_TO_UINT (data) & kNaClBundleMask) == 0);
716         g_assert ((newsize & kNaClBundleMask) == 0);
717         status = nacl_dyncode_create (code, data, newsize);
718         if (status != 0) {
719                 unsigned char *codep;
720                 fprintf(stderr, "Error creating Native Client dynamic code section attempted to be\n"
721                                 "emitted at %p (hex dissasembly of code follows):\n", code);
722                 for (codep = data; codep < data + newsize; codep++)
723                         fprintf(stderr, "%02x ", *codep);
724                 fprintf(stderr, "\n");
725                 g_assert_not_reached ();
726         }
727         g_hash_table_remove (cman->hash, data);
728 # ifndef USE_JUMP_TABLES
729         g_assert (data == patch_source_base[patch_current_depth]);
730         g_assert (code == patch_dest_base[patch_current_depth]);
731         patch_current_depth--;
732         g_assert (patch_current_depth >= -1);
733 # endif
734         free (data);
735 #endif
736 }
737
738 #if defined(__native_client_codegen__) && defined(__native_client__)
739 void *
740 nacl_code_manager_get_code_dest (MonoCodeManager *cman, void *data)
741 {
742         return g_hash_table_lookup (cman->hash, data);
743 }
744 #endif
745
746 /**
747  * mono_code_manager_size:
748  * @cman: a code manager
749  * @used_size: pointer to an integer for the result
750  *
751  * This function can be used to get statistics about a code manager:
752  * the integer pointed to by @used_size will contain how much
753  * memory is actually used inside the code managed @cman.
754  *
755  * Returns: the amount of memory allocated in @cman
756  */
757 int
758 mono_code_manager_size (MonoCodeManager *cman, int *used_size)
759 {
760         CodeChunk *chunk;
761         guint32 size = 0;
762         guint32 used = 0;
763         for (chunk = cman->current; chunk; chunk = chunk->next) {
764                 size += chunk->size;
765                 used += chunk->pos;
766         }
767         for (chunk = cman->full; chunk; chunk = chunk->next) {
768                 size += chunk->size;
769                 used += chunk->pos;
770         }
771         if (used_size)
772                 *used_size = used;
773         return size;
774 }
775
776 #ifdef __native_client_codegen__
777 # if defined(TARGET_ARM)
778 /* Fill empty space with UDF instruction used as halt on ARM. */
779 void
780 mono_nacl_fill_code_buffer (guint8 *data, int size)
781 {
782         guint32* data32 = (guint32*)data;
783         int i;
784         g_assert(size % 4 == 0);
785         for (i = 0; i < size / 4; i++)
786                 data32[i] = 0xE7FEDEFF;
787 }
788 # elif (defined(TARGET_X86) || defined(TARGET_AMD64))
789 /* Fill empty space with HLT instruction */
790 void
791 mono_nacl_fill_code_buffer(guint8 *data, int size)
792 {
793         memset (data, 0xf4, size);
794 }
795 # else
796 #  error "Not ported"
797 # endif
798 #endif