bool MM_VerboseBuffer::ensureCapacity(MM_EnvironmentBase *env, uintptr_t spaceNeeded) { MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); bool result = true; if(freeSpace() < spaceNeeded) { /* Not enough space in the current buffer - try to alloc a larger one and use that */ char *oldBuffer = _buffer; uintptr_t currentSize = this->currentSize(); uintptr_t newStringLength = currentSize + spaceNeeded; uintptr_t newSize = newStringLength + (newStringLength / 2); char* newBuffer = (char *) extensions->getForge()->allocate(newSize, MM_AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if(NULL == newBuffer) { result = false; } else { _buffer = newBuffer; /* Got a new buffer - initialize it */ _bufferTop = _buffer + newSize; reset(); /* Copy across the contents of the old buffer */ strcpy(_buffer, oldBuffer); _bufferAlloc += currentSize; /* Delete the old buffer */ extensions->getForge()->free(oldBuffer); } } return result; }
bool MM_VerboseWriter::initialize(MM_EnvironmentBase* env) { OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary()); MM_GCExtensionsBase* ext = env->getExtensions(); /* Initialize _header */ const char* version = omrgc_get_version(env->getOmrVM()); /* The length is -2 for the "%s" in VERBOSEGC_HEADER and +1 for '\0' */ uintptr_t headerLength = strlen(version) + strlen(VERBOSEGC_HEADER) - 1; _header = (char*)ext->getForge()->allocate(sizeof(char) * headerLength, OMR::GC::AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if (NULL == _header) { return false; } omrstr_printf(_header, headerLength, VERBOSEGC_HEADER, version); /* Initialize _footer */ uintptr_t footerLength = strlen(VERBOSEGC_FOOTER) + 1; _footer = (char*)ext->getForge()->allocate(sizeof(char) * footerLength, OMR::GC::AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if (NULL == _footer) { ext->getForge()->free(_header); return false; } omrstr_printf(_footer, footerLength, VERBOSEGC_FOOTER); return true; }
void MM_VerboseWriter::tearDown(MM_EnvironmentBase* env) { MM_GCExtensionsBase* ext = env->getExtensions(); ext->getForge()->free(_header); _header = NULL; ext->getForge()->free(_footer); _footer = NULL; }
/** * Probe the file system for existing files. Determine * the first number which is unused, or the number of the oldest * file if all numbers are used. * @return the first file number to use (starting at 0), or -1 on failure */ intptr_t MM_VerboseWriterFileLogging::findInitialFile(MM_EnvironmentBase *env) { OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary()); MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); int64_t oldestTime = J9CONST64(0x7FFFFFFFFFFFFFFF); /* the highest possible time. */ intptr_t oldestFile = 0; if (_mode != rotating_files) { /* nothing to do */ return 0; } for (uintptr_t currentFile = 0; currentFile < _numFiles; currentFile++) { char *filenameToOpen = expandFilename(env, currentFile); if (NULL == filenameToOpen) { return -1; } int64_t thisTime = omrfile_lastmod(filenameToOpen); extensions->getForge()->free(filenameToOpen); if (thisTime < 0) { /* file doesn't exist, or some other problem reading the file */ oldestFile = currentFile; break; } else if (thisTime < oldestTime) { oldestTime = thisTime; oldestFile = currentFile; } } return oldestFile; }
/** * Free the buffer object */ void MM_VerboseBuffer::kill(MM_EnvironmentBase *env) { tearDown(env); MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); extensions->getForge()->free(this); }
/** * Free the buffer itself */ void MM_VerboseBuffer::tearDown(MM_EnvironmentBase *env) { if(NULL != _buffer) { MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); extensions->getForge()->free(_buffer); } }
/** * Opens the file to log output to and prints the header. * @return true on sucess, false otherwise */ bool MM_VerboseWriterFileLoggingSynchronous::openFile(MM_EnvironmentBase *env) { OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary()); MM_GCExtensionsBase* extensions = env->getExtensions(); const char* version = omrgc_get_version(env->getOmrVM()); char *filenameToOpen = expandFilename(env, _currentFile); if (NULL == filenameToOpen) { return false; } _logFileDescriptor = omrfile_open(filenameToOpen, EsOpenRead | EsOpenWrite | EsOpenCreate | EsOpenTruncate, 0666); if(-1 == _logFileDescriptor) { char *cursor = filenameToOpen; /** * This may have failed due to directories in the path not being available. * Try to create these directories and attempt to open again before failing. */ while ( (cursor = strchr(++cursor, DIR_SEPARATOR)) != NULL ) { *cursor = '\0'; omrfile_mkdir(filenameToOpen); *cursor = DIR_SEPARATOR; } /* Try again */ _logFileDescriptor = omrfile_open(filenameToOpen, EsOpenRead | EsOpenWrite | EsOpenCreate | EsOpenTruncate, 0666); if (-1 == _logFileDescriptor) { _manager->handleFileOpenError(env, filenameToOpen); extensions->getForge()->free(filenameToOpen); return false; } } extensions->getForge()->free(filenameToOpen); omrfile_printf(_logFileDescriptor, getHeader(env), version); return true; }
/** * Tear down the structures managed by the MM_VerboseWriterFileLogging. * Tears down the verbose buffer. */ void MM_VerboseWriterFileLogging::tearDown(MM_EnvironmentBase *env) { OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary()); MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); omrstr_free_tokens(_tokens); _tokens = NULL; extensions->getForge()->free(_filename); _filename = NULL; MM_VerboseWriter::tearDown(env); }
void MM_MemoryPoolSplitAddressOrderedListBase::tearDown(MM_EnvironmentBase* env) { MM_MemoryPool::tearDown(env); if (NULL != _sweepPoolState) { MM_Collector* globalCollector = _extensions->getGlobalCollector(); Assert_MM_true(NULL != globalCollector); globalCollector->deleteSweepPoolState(env, _sweepPoolState); } if (NULL != _heapFreeLists) { for (uintptr_t i = 0; i < _heapFreeListCountExtended; ++i) { _heapFreeLists[i].tearDown(); } } MM_GCExtensionsBase* extensions = env->getExtensions(); extensions->getForge()->free(_heapFreeLists); extensions->getForge()->free(_currentThreadFreeList); if (NULL != _largeObjectAllocateStats) { _largeObjectAllocateStats->kill(env); _largeObjectAllocateStats = NULL; } if (NULL != _largeObjectAllocateStatsForFreeList) { for (uintptr_t i = 0; i < _heapFreeListCountExtended; ++i) { _largeObjectAllocateStatsForFreeList[i].tearDown(env); } extensions->getForge()->free(_largeObjectAllocateStatsForFreeList); _largeObjectAllocateStatsForFreeList = NULL; } _largeObjectCollectorAllocateStatsForFreeList = NULL; _resetLock.tearDown(); }
MM_VerboseManagerImpl * MM_VerboseManagerImpl::newInstance(MM_EnvironmentBase *env, OMR_VM* vm) { MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(vm); MM_VerboseManagerImpl *verboseManager = (MM_VerboseManagerImpl *)extensions->getForge()->allocate(sizeof(MM_VerboseManagerImpl), OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (verboseManager) { new(verboseManager) MM_VerboseManagerImpl(vm); if(!verboseManager->initialize(env)) { verboseManager->kill(env); verboseManager = NULL; } } return verboseManager; }
/** * Instantiate a new buffer object * @param size Buffer size */ MM_VerboseBuffer * MM_VerboseBuffer::newInstance(MM_EnvironmentBase *env, uintptr_t size) { MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); MM_VerboseBuffer *verboseBuffer = (MM_VerboseBuffer *) extensions->getForge()->allocate(sizeof(MM_VerboseBuffer), MM_AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if(NULL != verboseBuffer) { new(verboseBuffer) MM_VerboseBuffer(env); if (!verboseBuffer->initialize(env, size)) { verboseBuffer->kill(env); verboseBuffer = NULL; } } return verboseBuffer; }
MM_VerboseHandlerOutput * MM_VerboseHandlerOutput::newInstance(MM_EnvironmentBase *env, MM_VerboseManager *manager) { MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); MM_VerboseHandlerOutput *verboseHandlerOutput = (MM_VerboseHandlerOutput*)extensions->getForge()->allocate(sizeof(MM_VerboseHandlerOutput), OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL != verboseHandlerOutput) { new(verboseHandlerOutput) MM_VerboseHandlerOutput(extensions); if(!verboseHandlerOutput->initialize(env, manager)) { verboseHandlerOutput->kill(env); verboseHandlerOutput = NULL; } } return verboseHandlerOutput; }
/** * Initialization */ MM_CollectorLanguageInterfaceImpl * MM_CollectorLanguageInterfaceImpl::newInstance(MM_EnvironmentBase *env) { MM_CollectorLanguageInterfaceImpl *cli = NULL; OMR_VM *omrVM = env->getOmrVM(); MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(omrVM); cli = (MM_CollectorLanguageInterfaceImpl *)extensions->getForge()->allocate(sizeof(MM_CollectorLanguageInterfaceImpl), OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL != cli) { new(cli) MM_CollectorLanguageInterfaceImpl(omrVM); if (!cli->initialize(omrVM)) { cli->kill(env); cli = NULL; } } return cli; }
/** * Generate an expanded filename based on currentFile. * The caller is responsible for freeing the returned memory. * * @param env the current thread * @param currentFile the current file number to substitute into the filename template * * @return NULL on failure, allocated memory on success */ char* MM_VerboseWriterFileLogging::expandFilename(MM_EnvironmentBase *env, uintptr_t currentFile) { OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary()); MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); if (_mode == rotating_files) { omrstr_set_token(_tokens, "seq", "%03zu", currentFile + 1); /* plus one so the filenames start from .001 instead of .000 */ } uintptr_t len = omrstr_subst_tokens(NULL, 0, _filename, _tokens); char *filenameToOpen = (char*)extensions->getForge()->allocate(len, OMR::GC::AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if (NULL != filenameToOpen) { omrstr_subst_tokens(filenameToOpen, len, _filename, _tokens); } return filenameToOpen; }
/** * Initialize the buffer object * @param size Buffer size */ bool MM_VerboseBuffer::initialize(MM_EnvironmentBase *env, uintptr_t size) { MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); if(0 == size) { return false; } if(NULL == (_buffer = (char *) extensions->getForge()->allocate(size, MM_AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()))) { return false; } _bufferTop = _buffer + size; reset(); return true; }
/** * Create a new MM_VerboseWriterFileLoggingSynchronous instance. * @return Pointer to the new MM_VerboseWriterFileLoggingSynchronous. */ MM_VerboseWriterFileLoggingSynchronous * MM_VerboseWriterFileLoggingSynchronous::newInstance(MM_EnvironmentBase *env, MM_VerboseManager *manager, char *filename, uintptr_t numFiles, uintptr_t numCycles) { MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); MM_VerboseWriterFileLoggingSynchronous *agent = (MM_VerboseWriterFileLoggingSynchronous *)extensions->getForge()->allocate(sizeof(MM_VerboseWriterFileLoggingSynchronous), OMR::GC::AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if(agent) { new(agent) MM_VerboseWriterFileLoggingSynchronous(env, manager); if(!agent->initialize(env, filename, numFiles, numCycles)) { agent->kill(env); agent = NULL; } } return agent; }
/** * Initialize the _filename field based on filename. * * Since token substitution only supports tokens starting with %, all # characters in the * filename will be replaced with %seq (unless the # is already preceded by an odd number * of % signs, in which case it is replaced with seq). * * e.g. foo# --> foo%seq * foo%# --> foo%seq * foo%%# --> foo%%%seq * * If %seq or %# is not specified, and if rotating logs have been requested, ".%seq" is * appended to the log name. * * If the resulting filename is too large to fit in the buffer, it is truncated. * * @param[in] env the current environment * @param[in] filename the user specified filename * * @return true on success, false on failure */ bool MM_VerboseWriterFileLogging::initializeFilename(MM_EnvironmentBase *env, const char *filename) { MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(env->getOmrVM()); if (_mode == rotating_files) { const char* read = filename; /* count the number of hashes in the source string */ uintptr_t hashCount = 0; for (read = filename; '\0' != *read; read++) { if ('#' == *read) { hashCount++; } } /* allocate memory for the copied template filename */ uintptr_t nameLen = strlen(filename) + 1; if (hashCount > 0) { /* each # expands into %seq, so for each # add 3 to len */ nameLen += hashCount * (sizeof("seq") - 1); } else { /* if there are no hashes we may append .%seq to the end */ nameLen += sizeof(".%seq") - 1; } _filename = (char*)extensions->getForge()->allocate(nameLen, OMR::GC::AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if (NULL == _filename) { return false; } /* copy the original filename into the allocated memory, expanding #s to %seq */ bool foundSeq = false; bool oddPercents = false; char* write = _filename; for (read = filename; '\0' != *read; read++) { /* check to see if %seq appears in the source filename */ if (oddPercents && (0 == strncmp(read, "seq", 3))) { foundSeq = true; } if ('#' == *read) { strcpy(write, oddPercents ? "seq" : "%seq"); write += strlen(write); } else { *write++ = *read; } oddPercents = ('%' == *read) ? !oddPercents : false; } *write = '\0'; if ( (false == foundSeq) && (0 == hashCount) ) { strcpy(write, ".%seq"); } } else { _filename = (char*)extensions->getForge()->allocate(strlen(filename) + 1, OMR::GC::AllocationCategory::DIAGNOSTIC, OMR_GET_CALLSITE()); if (NULL == _filename) { return false; } strcpy(_filename, filename); } return true; }
bool MM_MemoryPoolSplitAddressOrderedListBase::initialize(MM_EnvironmentBase* env) { MM_GCExtensionsBase* extensions = env->getExtensions(); if (!MM_MemoryPool::initialize(env)) { return false; } /* * Create Sweep Pool State for MPAOL */ MM_Collector* globalCollector = _extensions->getGlobalCollector(); Assert_MM_true(NULL != globalCollector); _sweepPoolState = static_cast<MM_SweepPoolState*>(globalCollector->createSweepPoolState(env, this)); if (NULL == _sweepPoolState) { return false; } /* * Get Sweep Pool Manager for MPAOL * For platforms it doesn't required still be NULL */ _sweepPoolManager = extensions->sweepPoolManagerSmallObjectArea; _currentThreadFreeList = (uintptr_t*)extensions->getForge()->allocate(sizeof(uintptr_t) * _heapFreeListCount, MM_AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL == _currentThreadFreeList) { return false; } else { for (uintptr_t i = 0; i < _heapFreeListCount; ++i) { _currentThreadFreeList[i] = 0; } } _heapFreeLists = (J9ModronHeapFreeList*)extensions->getForge()->allocate(sizeof(J9ModronHeapFreeList) * _heapFreeListCountExtended, MM_AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL == _heapFreeLists) { return false; } else { memset(_heapFreeLists, 0, sizeof(J9ModronHeapFreeList) * _heapFreeListCountExtended); for (uintptr_t i = 0; i < _heapFreeListCountExtended; ++i) { if (!_heapFreeLists[i].initialize(env)) { return false; } } _referenceHeapFreeList = &(_heapFreeLists[0]._freeList); } /* set multiple factor = 2 for doubling _maxVeryLargeEntrySizes to avoid run out of _veryLargeEntryPool (minus count during decrement) */ _largeObjectAllocateStats = MM_LargeObjectAllocateStats::newInstance(env, (uint16_t)extensions->largeObjectAllocationProfilingTopK, extensions->largeObjectAllocationProfilingThreshold, extensions->largeObjectAllocationProfilingVeryLargeObjectThreshold, (float)extensions->largeObjectAllocationProfilingSizeClassRatio / (float)100.0, _extensions->heap->getMaximumMemorySize(), _extensions->tlhMaximumSize + _minimumFreeEntrySize, _extensions->tlhMinimumSize, 2); if (NULL == _largeObjectAllocateStats) { return false; } /* If we ever subclass MM_LargeObjectAllocateStats we will have to allocate this as an array of pointers to MM_LargeObjectAllocateStats and invoke newInstance instead of just initialize * Than, we may also need to virtualize initialize() and tearDown(). */ _largeObjectAllocateStatsForFreeList = (MM_LargeObjectAllocateStats*)extensions->getForge()->allocate(sizeof(MM_LargeObjectAllocateStats) * _heapFreeListCountExtended, MM_AllocationCategory::FIXED, OMR_GET_CALLSITE()); if (NULL == _largeObjectAllocateStatsForFreeList) { return false; } else { for (uintptr_t i = 0; i < _heapFreeListCountExtended; ++i) { new (&_largeObjectAllocateStatsForFreeList[i]) MM_LargeObjectAllocateStats(); /* set multiple factor = 2 for doubling _maxVeryLargeEntrySizes to avoid run out of _veryLargeEntryPool (minus count during decrement) */ if (!_largeObjectAllocateStatsForFreeList[i].initialize(env, (uint16_t)extensions->largeObjectAllocationProfilingTopK, extensions->largeObjectAllocationProfilingThreshold, extensions->largeObjectAllocationProfilingVeryLargeObjectThreshold, (float)extensions->largeObjectAllocationProfilingSizeClassRatio / (float)100.0, _extensions->heap->getMaximumMemorySize(), _extensions->tlhMaximumSize + _minimumFreeEntrySize, _extensions->tlhMinimumSize, 2)) { return false; } } } /* At this moment we do not know who is creator of this pool, so we do not set _largeObjectCollectorAllocateStatsForFreeList yet. * Tenure SubSpace for Gencon will set _largeObjectCollectorAllocateStatsForFreeList to _largeObjectCollectorAllocateStatsForFreeList (we append collector stats to mutator stats) * Tenure SubSpace for Flat will leave _largeObjectCollectorAllocateStatsForFreeList at NULL (no interest in collector stats) * We do not even need _largeObjectCollectorAllocateStats here (as we do in plain MPAOL) - we'll just merge whatever _largeObjectCollectorAllocateStatsForFreeList contatins (appended Collector stats or not) */ if (!_resetLock.initialize(env, &extensions->lnrlOptions, "MM_MemoryPoolSplitAddressOrderedList:_resetLock")) { return false; } return true; }