コード例 #1
0
ファイル: HeapVirtualMemory.cpp プロジェクト: dinogun/omr
/**
 * Attach a physical arena of the specified size to the receiver.
 * This reserves the address space within the receiver for the arena, and connects the arena to the list
 * of those associated to the receiver (in address order).
 * 
 * @return true if the arena was attached successfully, false otherwise.
 * @note The memory reseved is not commited.
 */
bool
MM_HeapVirtualMemory::attachArena(MM_EnvironmentBase* env, MM_PhysicalArena* arena, uintptr_t size)
{
	/* Sanity check of the size */
	if (getMaximumMemorySize() < size) {
		return false;
	}

	MM_GCExtensionsBase* extensions = env->getExtensions();
	MM_MemoryManager* memoryManager = extensions->memoryManager;

	/* Find the insertion point for the currentArena */
	void* candidateBase = memoryManager->getHeapBase(&_vmemHandle);
	MM_PhysicalArena* insertionHead = NULL;
	MM_PhysicalArena* insertionTail = _physicalArena;
	MM_PhysicalArena* currentArena = arena;

	while (insertionTail) {
		if ((((uintptr_t)insertionTail->getLowAddress()) - ((uintptr_t)candidateBase)) >= size) {
			break;
		}

		candidateBase = insertionTail->getHighAddress();

		insertionHead = insertionTail;
		insertionTail = insertionTail->getNextArena();
	}

	/* If we have reached the end of the currentArena list, check if there is room between the candidateBase
	 * and the end of virtual memory */
	if (!insertionTail) {
		if ((memoryManager->calculateOffsetToHeapTop(&_vmemHandle, candidateBase)) < size) {
			return false;
		}
	}

	/* Connect the physical currentArena into the list at the appropriate point */
	currentArena->setPreviousArena(insertionHead);
	currentArena->setNextArena(insertionTail);

	if (insertionTail) {
		insertionTail->setPreviousArena(currentArena);
	}

	if (insertionHead) {
		insertionHead->setNextArena(currentArena);
	} else {
		_physicalArena = currentArena;
	}

	currentArena->setLowAddress(candidateBase);
	currentArena->setHighAddress((void*)(((uint8_t*)candidateBase) + size));

	/* Set the arena state to being attached */
	arena->setAttached(true);

	return true;
}