Path: blob/master/runtime/gc_trace_vlhgc/TgcInterRegionRememberedSetDemographics.cpp
5986 views
/*******************************************************************************1* Copyright (c) 1991, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "j9.h"23#include "j9cfg.h"24#include "j9port.h"25#include "Tgc.hpp"26#include "mmhook.h"2728#include <string.h>2930#include "GCExtensions.hpp"31#include "TgcExtensions.hpp"3233#include "EnvironmentBase.hpp"34#include "HashTableIterator.hpp"35#include "HeapMapIterator.hpp"36#include "HeapRegionDescriptorVLHGC.hpp"37#include "HeapRegionIteratorVLHGC.hpp"38#include "HeapRegionManager.hpp"39#include "ParallelDispatcher.hpp"40#include "ParallelTask.hpp"4142struct ClassTableEntry {43J9Class *clazz; /**< The class represented by this entry */44UDATA rememberedInstances; /**< The number of instances of the class with references out of their own region */45UDATA totalInstances; /**< The total number of instances of the class encountered */4647static UDATA hash(void *key, void *userData) { return (UDATA)((ClassTableEntry*)key)->clazz; }48static UDATA equal(void *leftKey, void *rightKey, void *userData) { return ((ClassTableEntry*)leftKey)->clazz == ((ClassTableEntry*)rightKey)->clazz; }49};5051static void reportInterRegionRememberedSetDemographics(MM_EnvironmentBase *env);52static void tgcHookIncrementStart(J9HookInterface** hookInterface, UDATA eventNum, void* eventData, void* userData);53static void insertIntoSortedList(ClassTableEntry* entry, ClassTableEntry* list, UDATA listCount);5455class TgcParallelHeapWalkTask : public MM_ParallelTask56{57/* Data Members */58private:59protected:60public:6162/* Member Functions */63private:64protected:65public:66virtual UDATA getVMStateID(void) { return OMRVMSTATE_GC_TGC; }67virtual void run(MM_EnvironmentBase *env);6869TgcParallelHeapWalkTask(MM_EnvironmentBase *env, MM_ParallelDispatcher *dispatcher)70: MM_ParallelTask(env, dispatcher)71{72_typeId = __FUNCTION__;73}74};7576void77TgcParallelHeapWalkTask::run(MM_EnvironmentBase *env)78{79UDATA errorCount = 0;80UDATA totalRememberedObjects = 0;81MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);82MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);83MM_HeapMap *markMap = extensions->previousMarkMap;84J9HashTable *hashTable = hashTableNew(env->getPortLibrary(), J9_GET_CALLSITE(), 8*1024, sizeof(ClassTableEntry), sizeof(char *), 0, OMRMEM_CATEGORY_MM, ClassTableEntry::hash, ClassTableEntry::equal, NULL, NULL);8586if (NULL == hashTable) {87errorCount += 1;88} else {89GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager);90MM_HeapRegionDescriptorVLHGC *region = NULL;91while(NULL != (region = regionIterator.nextRegion())) {92if (region->hasValidMarkMap()) {93if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {94MM_HeapMapIterator mapIterator(extensions, markMap, (UDATA *)region->getLowAddress(), (UDATA *)region->getHighAddress(), false);95J9Object *objectPtr = NULL;96while(NULL != (objectPtr = mapIterator.nextObject())) {97ClassTableEntry exemplar;98exemplar.clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, env);99exemplar.rememberedInstances = 0;100exemplar.totalInstances = 0;101ClassTableEntry *entry = (ClassTableEntry *)hashTableAdd(hashTable, &exemplar);102103if (NULL == entry) {104errorCount += 1;105} else {106entry->totalInstances += 1;107if (extensions->objectModel.isRemembered(objectPtr)) {108entry->rememberedInstances += 1;109totalRememberedObjects += 1;110}111}112}113}114}115}116}117118/*119* Merge data120*/121omrthread_monitor_enter(tgcExtensions->_interRegionRememberedSetDemographics.mutex);122if (NULL != hashTable) {123J9HashTable *sharedHashTable = tgcExtensions->_interRegionRememberedSetDemographics.classHashTable;124GC_HashTableIterator hashTableIterator(hashTable);125ClassTableEntry *entry = NULL;126while(NULL != (entry = (ClassTableEntry*)hashTableIterator.nextSlot())) {127if (entry->rememberedInstances > 0) {128ClassTableEntry exemplar;129exemplar.clazz = entry->clazz;130exemplar.rememberedInstances = 0;131exemplar.totalInstances = 0;132ClassTableEntry *sharedEntry = (ClassTableEntry *)hashTableAdd(sharedHashTable, &exemplar);133if (NULL == sharedEntry) {134errorCount += 1;135} else {136sharedEntry->rememberedInstances += entry->rememberedInstances;137sharedEntry->totalInstances += entry->totalInstances;138}139}140}141}142tgcExtensions->_interRegionRememberedSetDemographics.errorCount += errorCount;143tgcExtensions->_interRegionRememberedSetDemographics.totalRememberedObjects += totalRememberedObjects;144omrthread_monitor_exit(tgcExtensions->_interRegionRememberedSetDemographics.mutex);145146if (NULL != hashTable) {147hashTableFree(hashTable);148}149}150151152/**153* Report RSCL histogram prior to a collection154*/155static void156reportInterRegionRememberedSetDemographics(MM_EnvironmentBase *env)157{158MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);159MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);160J9HashTable *hashTable = tgcExtensions->_interRegionRememberedSetDemographics.classHashTable;161162tgcExtensions->_interRegionRememberedSetDemographics.incrementCount += 1;163tgcExtensions->_interRegionRememberedSetDemographics.errorCount = 0;164tgcExtensions->_interRegionRememberedSetDemographics.totalRememberedObjects = 0;165166tgcExtensions->printf("<rememberedSetDemographics increment=\"%zu\">\n", tgcExtensions->_interRegionRememberedSetDemographics.incrementCount);167168MM_ParallelDispatcher *dispatcher = extensions->dispatcher;169TgcParallelHeapWalkTask heapWalkTask(env, dispatcher);170dispatcher->run(env, &heapWalkTask);171172/* at this point, the helper threads have completed populating the shared hash table with the all classes with remembered instances */173174const UDATA listCount = 10;175ClassTableEntry sortedResults[listCount];176memset(sortedResults, 0, sizeof(sortedResults));177178GC_HashTableIterator hashTableIterator(hashTable);179ClassTableEntry *entry = NULL;180while(NULL != (entry = (ClassTableEntry*)hashTableIterator.nextSlot())) {181Assert_MM_true(0 != entry->rememberedInstances);182insertIntoSortedList(entry, sortedResults, listCount);183hashTableIterator.removeSlot();184}185186UDATA errorCount = tgcExtensions->_interRegionRememberedSetDemographics.errorCount;187UDATA totalRememberedObjects = tgcExtensions->_interRegionRememberedSetDemographics.totalRememberedObjects;188for (UDATA index = 0; index < listCount; index++) {189entry = &sortedResults[index];190J9Class *clazz = entry->clazz;191if (NULL != clazz) {192double fractionRemembered = (double)entry->rememberedInstances / (double)entry->totalInstances;193double fractionOfAllRemembered = (double)entry->rememberedInstances / (double)totalRememberedObjects;194tgcExtensions->printf("%8zu %.2f %.2f %p ", entry->rememberedInstances, fractionRemembered, fractionOfAllRemembered, clazz);195if (J9GC_CLASS_IS_ARRAY(clazz)) {196J9Class *leafComponentType = ((J9ArrayClass*)clazz)->leafComponentType;197J9UTF8 *name = J9ROMCLASS_CLASSNAME(leafComponentType->romClass);198UDATA arity = ((J9ArrayClass*)clazz)->arity;199char brackets[256];200Assert_MM_true(arity <= sizeof(brackets));201memset(brackets, '[', sizeof(brackets));202if (OBJECT_HEADER_SHAPE_MIXED == J9GC_CLASS_SHAPE(leafComponentType)) {203tgcExtensions->printf("%.*sL%.*s;\n", arity, brackets, J9UTF8_LENGTH(name), J9UTF8_DATA(name));204} else {205tgcExtensions->printf("%.*s%.*s\n", arity, brackets, J9UTF8_LENGTH(name), J9UTF8_DATA(name));206}207} else {208J9UTF8 *name = J9ROMCLASS_CLASSNAME(clazz->romClass);209tgcExtensions->printf("%.*s\n", J9UTF8_LENGTH(name), J9UTF8_DATA(name));210}211}212}213214if (0 != errorCount) {215tgcExtensions->printf("WARNING: Failed to allocate records for %zu class(es).\n", errorCount);216}217218tgcExtensions->printf("<rememberedSetDemographics/>\n");219}220221static void222insertIntoSortedList(ClassTableEntry* entry, ClassTableEntry* list, UDATA listCount)223{224for (UDATA index = 0; index < listCount; index++) {225if (entry->rememberedInstances > list[index].rememberedInstances) {226memmove(&list[index + 1], &list[index], (listCount - index - 1) * sizeof(list[0]));227list[index] = *entry;228break;229}230}231}232233static void234tgcHookIncrementStart(J9HookInterface** hookInterface, UDATA eventNum, void* eventData, void* userData)235{236OMR_VMThread *omrThread = ((MM_GCIncrementStartEvent*)eventData)->currentThread;237MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrThread);238reportInterRegionRememberedSetDemographics(env);239}240241242/**243* Initialize inter region remembered set tgc tracing.244* Initializes the TgcInterRegionRememberedSetExtensions object associated with irrs tgc tracing. Attaches hooks245* to the appropriate functions handling events used by irrs tgc tracing.246*/247bool248tgcInterRegionRememberedSetDemographicsInitialize(J9JavaVM *javaVM)249{250MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);251MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);252bool result = true;253254J9HashTable *hashTable = hashTableNew(OMRPORT_FROM_J9PORT(javaVM->portLibrary), J9_GET_CALLSITE(), 8*1024, sizeof(ClassTableEntry), sizeof(char *), 0, OMRMEM_CATEGORY_MM, ClassTableEntry::hash, ClassTableEntry::equal, NULL, NULL);255tgcExtensions->_interRegionRememberedSetDemographics.classHashTable = hashTable;256257if (NULL != hashTable) {258if (0 == omrthread_monitor_init_with_name(&tgcExtensions->_interRegionRememberedSetDemographics.mutex, 0, "InterRegionRememberedSetDemographics")) {259J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);260(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_GC_INCREMENT_START, tgcHookIncrementStart, OMR_GET_CALLSITE(), javaVM);261} else {262result = false;263}264} else {265result = false;266}267268tgcExtensions->_interRegionRememberedSetDemographics.incrementCount = 0;269270return result;271}272273void274tgcInterRegionRememberedSetDemographicsTearDown(J9JavaVM *javaVM)275{276MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);277MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);278279if (NULL != tgcExtensions->_interRegionRememberedSetDemographics.classHashTable) {280hashTableFree(tgcExtensions->_interRegionRememberedSetDemographics.classHashTable);281tgcExtensions->_interRegionRememberedSetDemographics.classHashTable = NULL;282}283284if (NULL != tgcExtensions->_interRegionRememberedSetDemographics.mutex) {285omrthread_monitor_destroy(tgcExtensions->_interRegionRememberedSetDemographics.mutex);286tgcExtensions->_interRegionRememberedSetDemographics.mutex = NULL;287288}289}290291292