Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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; 
}
Beispiel #5
0
/**
 * 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);
}
Beispiel #6
0
/**
 * 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();
}
Beispiel #10
0
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;
}
Beispiel #11
0
/**
 * 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;
}
Beispiel #12
0
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;
	
}
Beispiel #15
0
/**
 * 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;
}