void MM_OverflowStandard::handleOverflow(MM_EnvironmentBase *env) { if (env->_currentTask->synchronizeGCThreadsAndReleaseMaster(env, UNIQUE_ID)) { _overflow = false; MM_Heap *heap = _extensions->heap; MM_HeapRegionManager *regionManager = heap->getHeapRegionManager(); GC_HeapRegionIterator regionIterator(regionManager); MM_HeapRegionDescriptor *region = NULL; // MM_ParallelGlobalGC *globalCollector = (MM_ParallelGlobalGC *)_extensions->getGlobalCollector(); MM_MarkMap *markMap = env->getMarkingEnvironment()->markingExtensions()->markMap(); while((region = regionIterator.nextRegion()) != NULL) { GC_ObjectHeapIteratorAddressOrderedList objectIterator(_extensions, region, false); omrobjectptr_t object; while((object = objectIterator.nextObject()) != NULL) { /* search for double marked (overflowed) objects */ if ((markMap->isBitSet(object)) && (markMap->isBitSet((omrobjectptr_t)((uintptr_t)object + markMap->getObjectGrain())))) { /* clean overflow mark */ markMap->clearBit((omrobjectptr_t)((uintptr_t)object + markMap->getObjectGrain())); /* scan overflowed object */ OMR::App::ObjectScanner().scanObject(env, env->getMarkingEnvironment(), object, SCAN_REASON_OVERFLOWED_OBJECT); } } } env->_currentTask->releaseSynchronizedGCThreads(env); } }
/** * 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; } } } }
void MM_ConcurrentOverflow::handleOverflow(MM_EnvironmentBase *env) { MM_EnvironmentStandard *envStandard = MM_EnvironmentStandard::getEnvironment(env); if (envStandard->_currentTask->synchronizeGCThreadsAndReleaseMaster(env, UNIQUE_ID)) { _overflow = false; envStandard->_currentTask->releaseSynchronizedGCThreads(envStandard); } MM_Heap *heap = _extensions->heap; MM_HeapRegionManager *regionManager = heap->getHeapRegionManager(); GC_HeapRegionIterator regionIterator(regionManager); MM_HeapRegionDescriptor *region = NULL; MM_ConcurrentGC *collector = (MM_ConcurrentGC *)_extensions->getGlobalCollector(); MM_CardCleanerForMarking cardCleanerForMarking(collector->getMarkingScheme()); MM_ConcurrentCardTable *cardTable = collector->getCardTable(); while((region = regionIterator.nextRegion()) != NULL) { cardTable->cleanCardTableForRange(envStandard, &cardCleanerForMarking, region->getLowAddress(), region->getHighAddress()); } envStandard->_currentTask->synchronizeGCThreads(env, UNIQUE_ID); }
/* a helper to get the root region manager from the heap, since it was needed in so many place */ MM_HeapRegionManager *getHeapRegionManager() {return _heap->getHeapRegionManager();}