10 #include <sys/types.h>
16 #include "mono-codeman.h"
24 /* if a chunk has less than this amount of free space it's considered full */
25 #define MAX_WASTAGE 32
28 #define MAP_ANONYMOUS MAP_ANON
31 typedef struct _CodeChunck CodeChunk;
43 unsigned int flags: 8;
44 /* this number of bytes is available to resolve addresses far in memory */
45 unsigned int bsize: 24;
48 struct _MonoCodeManager {
54 mono_code_manager_new (void)
56 MonoCodeManager *cman = malloc (sizeof (MonoCodeManager));
65 free_chunklist (CodeChunk *chunk)
71 if (dead->flags == CODE_FLAG_MMAP) {
73 munmap (dead->data, dead->size);
75 } else if (dead->flags == CODE_FLAG_MALLOC) {
83 mono_code_manager_destroy (MonoCodeManager *cman)
85 free_chunklist (cman->full);
86 free_chunklist (cman->current);
90 /* fill all the memory with the 0x2a (42) value */
92 mono_code_manager_invalidate (MonoCodeManager *cman)
97 int fill_value = 0xcc; /* x86 break */
99 int fill_value = 0x2a;
102 for (chunk = cman->current; chunk; chunk = chunk->next)
103 memset (chunk->data, fill_value, chunk->size);
104 for (chunk = cman->full; chunk; chunk = chunk->next)
105 memset (chunk->data, fill_value, chunk->size);
109 mono_code_manager_foreach (MonoCodeManager *cman, MonoCodeManagerFunc func, void *user_data)
112 for (chunk = cman->current; chunk; chunk = chunk->next) {
113 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
116 for (chunk = cman->full; chunk; chunk = chunk->next) {
117 if (func (chunk->data, chunk->size, chunk->bsize, user_data))
123 query_pagesize (void)
125 #ifdef PLATFORM_WIN32
127 GetSystemInfo (&info);
128 return info.dwAllocationGranularity;
130 return getpagesize ();
134 /* BIND_ROOM is the divisor for the chunck of code size dedicated
135 * to binding branches (branches not reachable with the immediate displacement)
136 * bind_size = size/BIND_ROOM;
137 * we should reduce it and make MIN_PAGES bigger for such systems
139 #if defined(__ppc__) || defined(__powerpc__)
144 new_codechunk (int size)
146 static int pagesize = 0;
147 int minsize, flags = CODE_FLAG_MMAP;
148 int chunk_size, bsize = 0;
153 pagesize = query_pagesize ();
155 minsize = pagesize * MIN_PAGES;
157 chunk_size = minsize;
160 chunk_size += pagesize - 1;
161 chunk_size &= ~ (pagesize - 1);
164 bsize = chunk_size / BIND_ROOM;
165 if (chunk_size - size < bsize) {
166 chunk_size += pagesize;
171 /* does it make sense to use the mmap-like API? */
172 ptr = malloc (chunk_size);
175 flags = CODE_FLAG_MALLOC;
177 ptr = mmap (0, chunk_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
178 if (ptr == (void*)-1) {
179 int fd = open ("/dev/zero", O_RDONLY);
181 ptr = mmap (0, chunk_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
184 if (ptr == (void*)-1) {
185 ptr = malloc (chunk_size);
188 flags = CODE_FLAG_MALLOC;
192 /* Make sure the thunks area is zeroed */
193 if (flags == CODE_FLAG_MALLOC)
194 memset (ptr, 0, bsize);
196 chunk = malloc (sizeof (CodeChunk));
198 if (flags == CODE_FLAG_MALLOC)
202 munmap (ptr, chunk_size);
207 chunk->size = chunk_size;
209 chunk->flags = flags;
211 chunk->bsize = bsize;
213 /*printf ("code chunk at: %p\n", ptr);*/
218 mono_code_manager_reserve (MonoCodeManager *cman, int size)
220 CodeChunk *chunk, *prev;
224 size &= ~ (MIN_ALIGN - 1);
226 if (!cman->current) {
227 cman->current = new_codechunk (size);
232 for (chunk = cman->current; chunk; chunk = chunk->next) {
233 if (chunk->pos + size <= chunk->size) {
234 ptr = chunk->data + chunk->pos;
240 * no room found, move one filled chunk to cman->full
241 * to keep cman->current from growing too much
244 for (chunk = cman->current; chunk; prev = chunk, chunk = chunk->next) {
245 if (chunk->pos + MIN_ALIGN * 4 <= chunk->size)
248 prev->next = chunk->next;
250 cman->current = chunk->next;
252 chunk->next = cman->full;
256 chunk = new_codechunk (size);
259 chunk->next = cman->current;
260 cman->current = chunk;
266 * if we reserved too much room for a method and we didn't allocate
267 * already from the code manager, we can get back the excess allocation.
270 mono_code_manager_commit (MonoCodeManager *cman, void *data, int size, int newsize)
272 newsize += MIN_ALIGN;
273 newsize &= ~ (MIN_ALIGN - 1);
275 size &= ~ (MIN_ALIGN - 1);
277 if (cman->current && (size != newsize) && (data == cman->current->data + cman->current->pos - size)) {
278 cman->current->pos -= size - newsize;