Path: blob/master/runtime/gc_trace/TgcRootScanner.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2021 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 "mmhook.h"25#include "TgcRootScanner.hpp"2627#include "EnvironmentBase.hpp"28#include "GCExtensions.hpp"29#include "TgcExtensions.hpp"30#include "VMThreadListIterator.hpp"3132static void printRootScannerStats(OMR_VMThread *omrVMThread);33static void tgcHookGCEnd(J9HookInterface** hook, UDATA eventNumber, void* eventData, void* userData);3435/**36* XML attribute names corresponding to entities in the root scanner enumeration.37*38* @ref RootScannerEntity39*/40const static char *attributeNames[] = {41"unknown", /* RootScannerEntity_None */42"scavengerememberedset", /* RootScannerEntity_ScavengeRememberedSet */43"classes", /* RootScannerEntity_Classes */44"vmclassslots", /* RootScannerEntity_VMClassSlots */45"permanentclasses", /* RootScannerEntity_PermanentClasses */46"classloaders", /* RootScannerEntity_ClassLoaders */47"threads", /* RootScannerEntity_Threads */48"finalizableobjects", /* RootScannerEntity_FinalizableObjects */49"unfinalizedobjects", /* RootScannerEntity_UnfinalizedObjects */50"ownablesynchronizerobjects", /* RootScannerEntity_OwnableSynchronizerObjects */51"stringtable", /* RootScannerEntity_StringTable */52"jniglobalrefs", /* RootScannerEntity_JNIGlobalReferences */53"jniweakglobalrefs", /* RootScannerEntity_JNIWeakGlobalReferences */54"debuggerrefs", /* RootScannerEntity_DebuggerReferences */55"debuggerclassrefs", /* RootScannerEntity_DebuggerClassReferences */56"monitorrefs", /* RootScannerEntity_MonitorReferences */57"weakrefs", /* RootScannerEntity_WeakReferenceObjects */58"softrefs", /* RootScannerEntity_SoftReferenceObjects */59"phantomrefs", /* RootScannerEntity_PhantomReferenceObjects */60"jvmtiobjecttagtables", /* RootScannerEntity_JVMTIObjectTagTables */61"noncollectableobjects", /* RootScannerEntity_NonCollectableObjects */62"rememberedset", /* RootScannerEntity_RememberedSet */63"memoryareaobjects", /* RootScannerEntity_MemoryAreaObjects */64"metronomerememberedset", /* RootScannerEntity_MetronomeRememberedSet */65"classescomplete", /* RootScannerEntity_ClassesComplete */66"weakrefscomplete", /* RootScannerEntity_WeakReferenceObjectsComplete */67"softrefscomplete", /* RootScannerEntity_SoftReferenceObjectsComplete */68"phantomrefscomplete", /* RootScannerEntity_PhantomReferenceObjectsComplete */69"unfinalizedobjectscomplete", /* RootScannerEntity_UnfinalizedObjectsComplete */70"ownablesynchronizerobjectscomplete", /* RootScannerEntity_OwnableSynchronizerObjectsComplete */71"monitorlookupcaches", /* RootScannerEntity_MonitorLookupCaches */72"monitorlookupcachescomplete", /* RootScannerEntity_MonitorLookupCachesComplete */73"monitorreferenceobjectscomplete", /* RootScannerEntity_MonitorReferenceObjectsComplete */74"doubleMappedObjects", /* RootScannerEntity_DoubleMappedObjects */75};7677bool78tgcRootScannerInitialize(J9JavaVM *javaVM)79{80MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);8182if (!extensions->rootScannerStatsEnabled) {83extensions->rootScannerStatsEnabled = true;8485J9HookInterface** mmOmrHooks = J9_HOOK_INTERFACE(extensions->omrHookInterface);86(*mmOmrHooks)->J9HookRegisterWithCallSite(mmOmrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, tgcHookGCEnd, OMR_GET_CALLSITE(), NULL);87(*mmOmrHooks)->J9HookRegisterWithCallSite(mmOmrHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, tgcHookGCEnd, OMR_GET_CALLSITE(), NULL);88}8990return true;91}9293static void94printRootScannerStats(OMR_VMThread *omrVMThread)95{96J9VMThread *currentThread = (J9VMThread *)MM_EnvironmentBase::getEnvironment(omrVMThread)->getLanguageVMThread();97PORT_ACCESS_FROM_JAVAVM(currentThread->javaVM);98MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(currentThread->javaVM);99MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(currentThread);100char timestamp[32];101U_64 entityScanTimeTotal[RootScannerEntity_Count] = { 0 };102J9VMThread *thread;103104/* print only if at least one thread reported stats on at least one of its roots */105if (extensions->rootScannerStatsUsed) {106OMRPORT_ACCESS_FROM_J9PORT(PORTLIB);107omrstr_ftime_ex(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", j9time_current_time_millis(), OMRSTR_FTIME_FLAG_LOCAL);108tgcExtensions->printf("<scan timestamp=\"%s\">\n", timestamp);109110GC_VMThreadListIterator threadIterator(currentThread);111while (NULL != (thread = threadIterator.nextVMThread())) {112MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(thread->omrVMThread);113114/* print stats for this thread only if it reported stats on at least one of its roots */115if (((GC_WORKER_THREAD == env->getThreadType()) || (thread == currentThread)) && env->_rootScannerStats._statsUsed) {116tgcExtensions->printf("\t<thread id=\"%zu\"", env->getWorkerID());117118/* Scan collected entity data and print attribute/value pairs for entities that have119* collected data. Skip RootScannerEntity_None, located at index 0. */120for (UDATA entityIndex = 1; entityIndex < RootScannerEntity_Count; entityIndex++) {121if (0 != env->_rootScannerStats._entityScanTime[entityIndex]) {122U_64 scanTime = j9time_hires_delta(0, env->_rootScannerStats._entityScanTime[entityIndex], J9PORT_TIME_DELTA_IN_MICROSECONDS);123124tgcExtensions->printf(" %s=\"%llu.%03.3llu\"",125attributeNames[entityIndex],126scanTime / 1000,127scanTime % 1000);128129entityScanTimeTotal[entityIndex] += env->_rootScannerStats._entityScanTime[entityIndex];130}131}132133if (extensions->isMetronomeGC()) {134tgcExtensions->printf(" maxincrementtime=\"%llu.%03.3llu\" maxincremententity=\"%s\"",135env->_rootScannerStats._maxIncrementTime / 1000,136env->_rootScannerStats._maxIncrementTime % 1000,137attributeNames[env->_rootScannerStats._maxIncrementEntity]);138}139140tgcExtensions->printf("/>\n");141142/* Clear root scanner statistics collected for this thread, so data printed during143* this pass will not be duplicated */144env->_rootScannerStats.clear();145}146}147148/* Print totals for each root scanner entity */149tgcExtensions->printf("\t<total");150for (UDATA entityIndex = 1; entityIndex < RootScannerEntity_Count; entityIndex++) {151if (0 != entityScanTimeTotal[entityIndex]) {152U_64 scanTime = j9time_hires_delta(0, entityScanTimeTotal[entityIndex], J9PORT_TIME_DELTA_IN_MICROSECONDS);153154tgcExtensions->printf(" %s=\"%llu.%03.3llu\"",155attributeNames[entityIndex],156scanTime / 1000,157scanTime % 1000);158}159}160161tgcExtensions->printf("/>\n</scan>\n");162extensions->rootScannerStatsUsed = false;163}164}165166static void167tgcHookGCEnd(J9HookInterface** hook, UDATA eventNumber, void* eventData, void* userData)168{169MM_GCCycleEndEvent* event = (MM_GCCycleEndEvent*) eventData;170171printRootScannerStats(event->omrVMThread);172}173174175