コード例 #1
0
/**
 * 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;
}
コード例 #2
0
ファイル: mono-codeman.c プロジェクト: arttaylor/mono
/**
 * 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
}