/**
 * Walk all segments and calculate the maximum number of chunks needed to represent the current heap.
 * The chunk calculation is done on a per segment basis (no segment can represent memory from more than 1 chunk),
 * and partial sized chunks (ie: less than the chunk size) are reserved for any remaining space at the end of a
 * segment.
 * @return number of chunks required to represent the current heap memory.
 */
uintptr_t
MM_SweepHeapSectioningSegmented::calculateActualChunkNumbers() const
{
	uintptr_t totalChunkCount = 0;

	MM_HeapRegionDescriptor *region;
	MM_Heap *heap = _extensions->heap;
	MM_HeapRegionManager *regionManager = heap->getHeapRegionManager();
	GC_HeapRegionIterator regionIterator(regionManager);

	while((region = regionIterator.nextRegion()) != NULL) {
		if ((region)->isCommitted()) {
			/* TODO:  this must be rethought for Tarok since it treats all regions identically but some might require different sweep logic */
			MM_MemorySubSpace *subspace = region->getSubSpace();
			/* if this is a committed region, it requires a non-NULL subspace */
			Assert_MM_true(NULL != subspace);
			uintptr_t poolCount = subspace->getMemoryPoolCount();

			totalChunkCount += MM_Math::roundToCeiling(_extensions->parSweepChunkSize, region->getSize()) / _extensions->parSweepChunkSize;

			/* Add extra chunks if more than one memory pool */
			totalChunkCount += (poolCount - 1);
		}
	}

	return totalChunkCount;
}
Exemple #2
0
void
MM_MarkMap::initializeMarkMap(MM_EnvironmentBase *env)
{
	/* TODO: The multiplier should really be some constant defined globally */
	const uintptr_t MODRON_PARALLEL_MULTIPLIER = 32;
	uintptr_t heapAlignment = _extensions->heapAlignment;

	/* Determine the size of heap that a work unit of mark map clearing corresponds to */
	uintptr_t heapClearUnitFactor = env->_currentTask->getThreadCount();
	heapClearUnitFactor = ((heapClearUnitFactor == 1) ? 1 : heapClearUnitFactor * MODRON_PARALLEL_MULTIPLIER);
	uintptr_t heapClearUnitSize = _extensions->heap->getMemorySize() / heapClearUnitFactor;
	heapClearUnitSize = MM_Math::roundToCeiling(heapAlignment, heapClearUnitSize);

	/* Walk all object segments to determine what ranges of the mark map should be cleared */
	MM_HeapRegionDescriptor *region;
	MM_Heap *heap = _extensions->getHeap();
	MM_HeapRegionManager *regionManager = heap->getHeapRegionManager();
	GC_HeapRegionIterator regionIterator(regionManager);
	while(NULL != (region = regionIterator.nextRegion())) {
		if (region->isCommitted()) {
			/* Walk the segment in chunks the size of the heapClearUnit size, checking if the corresponding mark map
			 * range should  be cleared.
			 */
			uint8_t* heapClearAddress = (uint8_t*)region->getLowAddress();
			uintptr_t heapClearSizeRemaining = region->getSize();

			while(0 != heapClearSizeRemaining) {
				/* Calculate the size of heap that is to be processed */
				uintptr_t heapCurrentClearSize = (heapClearUnitSize > heapClearSizeRemaining) ? heapClearSizeRemaining : heapClearUnitSize;
				Assert_MM_true(heapCurrentClearSize > 0);

				/* Check if the thread should clear the corresponding mark map range for the current heap range */
				if(J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {
					/* Convert the heap address/size to its corresponding mark map address/size */
					/* NOTE: We calculate the low and high heap offsets, and build the mark map index and size values
					 * from these to avoid rounding errors (if we use the size, the conversion routine could get a different
					 * rounding result then the actual end address)
					 */
					uintptr_t heapClearOffset = ((uintptr_t)heapClearAddress) - _heapMapBaseDelta;
					uintptr_t heapMapClearIndex = convertHeapIndexToHeapMapIndex(env, heapClearOffset, sizeof(uintptr_t));
					uintptr_t heapMapClearSize =
						convertHeapIndexToHeapMapIndex(env, heapClearOffset + heapCurrentClearSize, sizeof(uintptr_t))
						- heapMapClearIndex;

					/* And clear the mark map */
					OMRZeroMemory((void *) (((uintptr_t)_heapMapBits) + heapMapClearIndex), heapMapClearSize);
				}

				/* Move to the next address range in the segment */
				heapClearAddress += heapCurrentClearSize;
				heapClearSizeRemaining -= heapCurrentClearSize;
			}
		}
	}
}
MM_HeapRegionDescriptor *
MM_HeapRegionManagerTarok::internalAcquireSingleTableRegion(MM_EnvironmentBase *env, MM_MemorySubSpace *subSpace, uintptr_t freeListIndex)
{
	Assert_MM_true(NULL != _freeRegionTable[freeListIndex]);

	/*since we only need one region, always return the first free region */
	MM_HeapRegionDescriptor *toReturn = _freeRegionTable[freeListIndex];

	_freeRegionTable[freeListIndex] = toReturn->_nextInSet;

	toReturn->_nextInSet = NULL;
	toReturn->_isAllocated = true;
	toReturn->associateWithSubSpace(subSpace);
	_totalHeapSize += toReturn->getSize();

	return toReturn;
}