/** * 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; }
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; }