/** * mono_code_manager_reserve_align: * \param cman a code manager * \param size size of memory to allocate * \param alignment power of two alignment value * Allocates at least \p size bytes of memory inside the code manager \p cman. * \returns the pointer to the allocated memory or NULL on failure */ void* mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment) { CodeChunk *chunk, *prev; void *ptr; guint32 align_mask = alignment - 1; g_assert (!cman->read_only); /* eventually allow bigger alignments, but we need to fix the dynamic alloc code to * handle this before */ g_assert (alignment <= MIN_ALIGN); if (cman->dynamic) { ++dynamic_code_alloc_count; dynamic_code_bytes_count += size; } if (!cman->current) { cman->current = new_codechunk (cman->last, cman->dynamic, size); if (!cman->current) return NULL; cman->last = cman->current; } for (chunk = cman->current; chunk; chunk = chunk->next) { if (ALIGN_INT (chunk->pos, alignment) + size <= chunk->size) { chunk->pos = ALIGN_INT (chunk->pos, alignment); /* Align the chunk->data we add to chunk->pos */ /* or we can't guarantee proper alignment */ ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos); chunk->pos = ((char*)ptr - chunk->data) + size; return ptr; } } /* * no room found, move one filled chunk to cman->full * to keep cman->current from growing too much */ prev = NULL; for (chunk = cman->current; chunk; prev = chunk, chunk = chunk->next) { if (chunk->pos + MIN_ALIGN * 4 <= chunk->size) continue; if (prev) { prev->next = chunk->next; } else { cman->current = chunk->next; } chunk->next = cman->full; cman->full = chunk; break; } chunk = new_codechunk (cman->last, cman->dynamic, size); if (!chunk) return NULL; chunk->next = cman->current; cman->current = chunk; cman->last = cman->current; chunk->pos = ALIGN_INT (chunk->pos, alignment); /* Align the chunk->data we add to chunk->pos */ /* or we can't guarantee proper alignment */ ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos); chunk->pos = ((char*)ptr - chunk->data) + size; return ptr; }
/** * mono_code_manager_reserve: * @cman: a code manager * @size: size of memory to allocate * @alignment: power of two alignment value * * Allocates at least @size bytes of memory inside the code manager @cman. * * Returns: the pointer to the allocated memory or #NULL on failure */ void* mono_code_manager_reserve_align (MonoCodeManager *cman, int size, int alignment) { #if !defined(__native_client__) || !defined(__native_client_codegen__) CodeChunk *chunk, *prev; void *ptr; guint32 align_mask = alignment - 1; g_assert (!cman->read_only); /* eventually allow bigger alignments, but we need to fix the dynamic alloc code to * handle this before */ g_assert (alignment <= MIN_ALIGN); if (cman->dynamic) { ++dynamic_code_alloc_count; dynamic_code_bytes_count += size; } if (!cman->current) { cman->current = new_codechunk (cman->last, cman->dynamic, size); if (!cman->current) return NULL; cman->last = cman->current; } for (chunk = cman->current; chunk; chunk = chunk->next) { if (ALIGN_INT (chunk->pos, alignment) + size <= chunk->size) { chunk->pos = ALIGN_INT (chunk->pos, alignment); /* Align the chunk->data we add to chunk->pos */ /* or we can't guarantee proper alignment */ ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos); chunk->pos = ((char*)ptr - chunk->data) + size; return ptr; } } /* * no room found, move one filled chunk to cman->full * to keep cman->current from growing too much */ prev = NULL; for (chunk = cman->current; chunk; prev = chunk, chunk = chunk->next) { if (chunk->pos + MIN_ALIGN * 4 <= chunk->size) continue; if (prev) { prev->next = chunk->next; } else { cman->current = chunk->next; } chunk->next = cman->full; cman->full = chunk; break; } chunk = new_codechunk (cman->last, cman->dynamic, size); if (!chunk) return NULL; chunk->next = cman->current; cman->current = chunk; cman->last = cman->current; chunk->pos = ALIGN_INT (chunk->pos, alignment); /* Align the chunk->data we add to chunk->pos */ /* or we can't guarantee proper alignment */ ptr = (void*)((((uintptr_t)chunk->data + align_mask) & ~(uintptr_t)align_mask) + chunk->pos); chunk->pos = ((char*)ptr - chunk->data) + size; return ptr; #else unsigned char *temp_ptr, *code_ptr; /* Round up size to next bundle */ alignment = kNaClBundleSize; size = (size + kNaClBundleSize) & (~kNaClBundleMask); /* Allocate a temp buffer */ temp_ptr = memalign (alignment, size); g_assert (((uintptr_t)temp_ptr & kNaClBundleMask) == 0); /* Allocate code space from the service runtime */ code_ptr = allocate_code (size); /* Insert pointer to code space in hash, keyed by buffer ptr */ g_hash_table_insert (cman->hash, temp_ptr, code_ptr); #ifndef USE_JUMP_TABLES nacl_jit_check_init (); patch_current_depth++; patch_source_base[patch_current_depth] = temp_ptr; patch_dest_base[patch_current_depth] = code_ptr; patch_alloc_size[patch_current_depth] = size; g_assert (patch_current_depth < kMaxPatchDepth); #endif return temp_ptr; #endif }