Path: blob/master/runtime/compiler/control/HookedByTheJit.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2022 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 <algorithm>23#include <limits.h>24#include <stdarg.h>25#include "bcnames.h"26#include "jithash.h"27#include "jitprotos.h"28#include "j9.h"29#include "j9cfg.h"30#include "j9modron.h"31#include "j9nonbuilder.h"32#include "j9consts.h"33#include "mmhook.h"34#include "mmomrhook.h"35#include "vmaccess.h"36#include "codegen/CodeGenerator.hpp"37#include "compile/CompilationTypes.hpp"38#include "compile/Method.hpp"39#include "compile/ResolvedMethod.hpp"40#include "control/OptimizationPlan.hpp"41#include "control/OptionsUtil.hpp"42#include "control/Recompilation.hpp"43#include "control/RecompilationInfo.hpp"44#include "control/CompilationController.hpp"45#include "env/ClassLoaderTable.hpp"46#include "env/CompilerEnv.hpp"47#include "env/IO.hpp"48#include "env/J2IThunk.hpp"49#include "env/PersistentCHTable.hpp"50#include "env/PersistentInfo.hpp"51#include "env/jittypes.h"52#include "env/ClassTableCriticalSection.hpp"53#include "env/VMAccessCriticalSection.hpp"54#include "env/VMJ9.h"55#include "env/VerboseLog.hpp"56#include "il/DataTypes.hpp"57#include "ilgen/IlGeneratorMethodDetails_inlines.hpp"58#include "infra/Monitor.hpp"59#include "infra/MonitorTable.hpp"60#include "infra/CriticalSection.hpp"61#include "optimizer/DebuggingCounters.hpp"62#include "optimizer/JProfilingBlock.hpp"63#include "runtime/CodeCacheManager.hpp"64#include "runtime/HookHelpers.hpp"65#include "runtime/MethodMetaData.h"66#include "runtime/RelocationRuntime.hpp"67#include "runtime/asmprotos.h"68#include "runtime/codertinit.hpp"69#include "control/MethodToBeCompiled.hpp"70#include "control/CompilationRuntime.hpp"71#include "control/CompilationThread.hpp"72#include "env/VMJ9.h"73#include "env/j9method.h"74#include "env/ut_j9jit.h"75#include "ilgen/J9ByteCodeIlGenerator.hpp"76#include "ilgen/J9ByteCodeIterator.hpp"77#include "runtime/IProfiler.hpp"78#include "runtime/HWProfiler.hpp"79#include "env/SystemSegmentProvider.hpp"80#if defined(J9VM_OPT_JITSERVER)81#include "control/JITServerHelpers.hpp"82#include "runtime/JITServerAOTDeserializer.hpp"83#include "runtime/JITServerIProfiler.hpp"84#include "runtime/JITServerStatisticsThread.hpp"85#include "runtime/Listener.hpp"86#endif /* defined(J9VM_OPT_JITSERVER) */8788extern "C" {89struct J9JavaVM;90}9192#if defined(J9ZOS390) && defined(TR_TARGET_32BIT)93#include <stdlib.h>9495#define PSAAOLD 0x224 ///< offset of current ASCB in prefixed save area (located at address 0x0)96#define ASCBLDA 0x30 ///< offset of LDA field in ASCB97#define LDASTRTA 0x3c ///< offset of user region start in LDA98#define LDASIZA 0x40 ///< offset of maximum user region size in LDA99#define LDAESTRA 0x4c ///< offset of extended user region start in LDA100#define LDAESIZA 0x50 ///< offset of maximum extended user region size in LDA101#define LDACRGTP 0x98 ///< offset of user region top in LDA102#define LDAERGTP 0x9c ///< offset of extended user region top in LDA103104struct LDA {105uint32_t padding1[15]; ///< Padding106void * strta; ///< User Region Start107uint32_t siza; ///< Max size of the User Region108uint32_t padding2[2]; ///< Padding109void * estra; ///< Extended User Region Start110uint32_t esiza; ///< Max size of the Extended User Region111uint32_t padding3[17]; ///< Padding112void * crgtp; ///< User Region Top113void * ergtp; ///< Extended User Region Top114};115#endif116117#ifdef J9VM_JIT_RUNTIME_INSTRUMENTATION118// extern until function is added to oti/jitprotos.h119extern "C" void shutdownJITRuntimeInstrumentation(J9JavaVM *vm);120#endif121122/* 1) Regular hooks123* These fire when a normal condition occurs.124* Ie: In the case of the "jitHookInitializeSendTarget" hook,125* the VM triggers the event as its initializing the send targets for a class.126* This is part of the normal code flow.127*/128129/* 2) Async hooks130* These fire when requested by an outside thread.131* The thread requesting the async event has each thread/requested thread stop at132* its next safepoint to acknowledge the event.133* The interrupted thread runs the handler and then continues its execution.134*/135136void137cgOnClassUnloading(void *loaderPtr)138{139#if defined(TR_TARGET_POWER) && defined(TR_HOST_POWER) && defined(TR_TARGET_64BIT)140if (TR::Compiler->target.cpu.isPower())141TR::CodeGenerator::ppcCGOnClassUnloading(loaderPtr);142#endif143}144145extern TR::Monitor *assumptionTableMutex;146147extern volatile bool shutdownSamplerThread;148149#if defined(AOTRT_DLL)150#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)151extern void rtHookClassUnload(J9HookInterface * *, UDATA , void *, void *);152extern void rtHookClassLoaderUnload(J9HookInterface * *, UDATA , void *, void *);153#endif154#endif155156#ifdef FIXUP_UNALIGNED157#ifdef J9VM_ENV_LITTLE_ENDIAN158#define BC_OP_U16(bcPtr) (((*(((uint8_t*)(bcPtr))+1))<<8) + (*((uint8_t*)(bcPtr))))159#else160#define BC_OP_U16(bcPtr) (((*((uint8_t*)(bcPtr)))<<8) + (*(((uint8_t*)(bcPtr))+1)))161#endif162#else163#define BC_OP_U16(bcPtr) (*((uint16_t*)(bcPtr)))164#endif165166167TR::OptionSet *findOptionSet(J9Method *method, bool isAOT)168{169TR::OptionSet *optionSet = NULL;170J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);171J9UTF8 *className;172J9UTF8 *name;173J9UTF8 *signature;174getClassNameSignatureFromMethod(method, className, name, signature);175char *methodSignature;176char arr[1024];177int32_t len = J9UTF8_LENGTH(className) + J9UTF8_LENGTH(name) + J9UTF8_LENGTH(signature) + 3;178if (len < 1024)179methodSignature = arr;180else181methodSignature = (char *) TR_Memory::jitPersistentAlloc(len);182183if (methodSignature)184{185sprintf(methodSignature, "%.*s.%.*s%.*s", J9UTF8_LENGTH(className), utf8Data(className), J9UTF8_LENGTH(name), utf8Data(name), J9UTF8_LENGTH(signature), utf8Data(signature));186187TR_FilterBST * filter = 0;188if (TR::Options::getDebug() && TR::Options::getDebug()->getCompilationFilters())189TR::Options::getDebug()->methodSigCanBeCompiled(methodSignature, filter, TR::Method::J9);190191int32_t index = filter ? filter->getOptionSet() : 0;192int32_t lineNum = filter ? filter->getLineNumber() : 0;193194bool hasBackwardBranches = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? true : false);195196optionSet = TR::Options::findOptionSet(index, lineNum, methodSignature, TR::Options::getInitialHotnessLevel(hasBackwardBranches), isAOT);197if (len >= 1024)198TR_Memory::jitPersistentFree(methodSignature);199}200201return optionSet;202}203204static void reportHook(J9VMThread *curThread, char *name, char *format=NULL, ...)205{206J9JITConfig * jitConfig = curThread->javaVM->jitConfig;207TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);208if ( TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks)209|| TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails))210{211TR_VerboseLog::CriticalSection vlogLock;212TR_VerboseLog::write(TR_Vlog_HK,"vmThread=%p hook %s ", curThread, name);213if (format)214{215va_list args;216va_start(args, format);217j9jit_vprintf(jitConfig, format, args);218va_end(args);219}220TR_VerboseLog::writeLine("");221}222}223224static void reportHookFinished(J9VMThread *curThread, char *name, char *format=NULL, ...)225{226J9JITConfig * jitConfig = curThread->javaVM->jitConfig;227TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);228if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails))229{230TR_VerboseLog::CriticalSection vlogLock;231TR_VerboseLog::writeLine(TR_Vlog_HD,"vmThread=%p hook %s finished ", curThread, name);232if (format)233{234va_list args;235va_start(args, format);236j9jit_vprintf(jitConfig, format, args);237va_end(args);238}239}240}241242static void reportHookDetail(J9VMThread *curThread, char *name, char *format, ...)243{244J9JITConfig * jitConfig = curThread->javaVM->jitConfig;245TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);246if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails))247{248TR_VerboseLog::CriticalSection vlogLock;249TR_VerboseLog::writeLine(TR_Vlog_HD,"vmThread=%p hook %s detail ", curThread, name);250va_list args;251va_start(args, format);252j9jit_vprintf(jitConfig, format, args);253va_end(args);254}255}256257extern "C" {258259extern void freeJITConfig(J9JITConfig *);260extern void stopSamplingThread(J9JITConfig *);261extern void getOutOfIdleStates(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason);262extern void getOutOfIdleStatesUnlocked(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason);263264265//***************************************************************************************266// Hooked by the JIT267//***************************************************************************************268269int32_t encodeCount(int32_t count)270{271return (count == -1) ? 0 : (count << 1) + 1;272}273274int32_t getCount(J9ROMMethod *romMethod, TR::Options *optionsJIT, TR::Options *optionsAOT)275{276int32_t count;277if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))278{279count = std::min(optionsJIT->getInitialBCount(), optionsAOT->getInitialBCount());280}281else282{283count = std::min(optionsJIT->getInitialCount(), optionsAOT->getInitialCount());284if (TR::Options::_smallMethodBytecodeSizeThreshold > 0)285{286uint32_t methodSize = TR::CompilationInfo::getMethodBytecodeSize(romMethod);287if ((int32_t)methodSize <= TR::Options::_smallMethodBytecodeSizeThreshold)288{289count = count << 3;290}291}292}293return count;294}295296297bool sharedCacheContainsProfilingInfoForMethod(J9VMThread *vmThread, TR::CompilationInfo *compInfo, J9ROMMethod * romMethod)298{299J9SharedClassConfig * scConfig = compInfo->getJITConfig()->javaVM->sharedClassConfig;300301if(!scConfig)302return false;303304unsigned char storeBuffer[1000];305uint32_t bufferLength=1000;306J9SharedDataDescriptor descriptor;307descriptor.address = storeBuffer;308descriptor.length = bufferLength;309descriptor.type = J9SHR_ATTACHED_DATA_TYPE_JITPROFILE;310descriptor.flags = J9SHR_ATTACHED_DATA_NO_FLAGS;311312IDATA dataIsCorrupt;313TR_IPBCDataStorageHeader *store = (TR_IPBCDataStorageHeader *)scConfig->findAttachedData(vmThread, romMethod, &descriptor, &dataIsCorrupt);314315if (!store)316return false;317318if (store != (TR_IPBCDataStorageHeader *)descriptor.address) // a stronger check, as found can be error value319return false;320321return true;322}323324325/// This is a helper function used by jitHookInitializeSendTarget().326/// This function calculates for the hash value for methods using method names.327/// The hash value will be eventually added to variable `count` in `jitHookInitializeSendTarget()` under some conditions.328/// The formula for the hash value is:329///330/// hashValue[0] = HASH_INIT_VALUE;331/// hashValue[i+1] = hashValue[i] * HASH_BASE_VALUE + name[i];332/// hashValue[length(name)] will be used as the hash value333static uint32_t initializeSendTargetHelperFuncHashValueForSpreading(J9Method* method)334{335// extract class name, method name, and signature336J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);337J9UTF8 *className;338J9UTF8 *name;339J9UTF8 *signature;340getClassNameSignatureFromMethod(method, className, name, signature);341char *classNameChar = utf8Data(className);342char *nameChar = utf8Data(name);343char *signatureChar = utf8Data(signature);344345// set the base and initial value for the hash value346// const uint32_t HASH_BASE_VALUE = 33;347const uint32_t HASH_INIT_VALUE = 5381;348349// get options350TR::Options * optionsJIT = TR::Options::getJITCmdLineOptions();351TR::Options * optionsAOT = TR::Options::getAOTCmdLineOptions();352353// extract the CAP of the hash value354uint32_t hashValueCap;355if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))356hashValueCap = std::max(optionsJIT->getMaxSpreadCountLoopy(), optionsAOT->getMaxSpreadCountLoopy());357else358hashValueCap = std::max(optionsJIT->getMaxSpreadCountLoopless(), optionsAOT->getMaxSpreadCountLoopless());359360// compute the hash value361uint32_t hashValue = HASH_INIT_VALUE;362for (uint32_t i = 0; i < J9UTF8_LENGTH(className); i++)363hashValue = (hashValue << 5) + hashValue + classNameChar[i];364for (uint32_t i = 0; i < J9UTF8_LENGTH(name); i++)365hashValue = (hashValue << 5) + hashValue + nameChar[i];366for (uint32_t i = 0; i < J9UTF8_LENGTH(signature); i++)367hashValue = (hashValue << 5) + hashValue + signatureChar[i];368hashValue = hashValue % hashValueCap;369370return hashValue;371}372373static bool highCodeCacheOccupancyThresholdReached = false;374375static void jitHookInitializeSendTarget(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData)376{377J9VMInitializeSendTargetEvent * event = (J9VMInitializeSendTargetEvent *)eventData;378379J9VMThread * vmThread = event->currentThread;380J9JITConfig* jitConfig = vmThread->javaVM->jitConfig;381TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);382383if ((jitConfig->runtimeFlags & J9JIT_DEFER_JIT) != 0)384return; // No need to set counts in this mode385386TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, vmThread);387388J9Method * method = event->method;389J9ROMMethod * romMethod = fe->getROMMethodFromRAMMethod(method);390391// Allow native and abstract methods to be initialized by the interpreter392if (romMethod->modifiers & (J9AccAbstract | J9AccNative))393{394TR::CompilationInfo::setInitialInvocationCountUnsynchronized(method,0);395return;396}397398TR::Options * optionsJIT = TR::Options::getJITCmdLineOptions();399TR::Options * optionsAOT = TR::Options::getAOTCmdLineOptions();400401method->methodRunAddress = jitGetCountingSendTarget(vmThread, method);402403bool countInOptionSet = false;404405if (TR::Options::getJITCmdLineOptions()->anOptionSetContainsACountValue())406{407TR::OptionSet * optionSet = findOptionSet(method, false);408if (optionSet)409{410optionsJIT = optionSet->getOptions();411countInOptionSet = true;412}413}414415if (TR::Options::getAOTCmdLineOptions()->anOptionSetContainsACountValue())416{417TR::OptionSet * optionSet = findOptionSet(method, true);418if (optionSet)419{420optionsAOT = optionSet->getOptions();421countInOptionSet = true;422}423}424425int32_t count = -1; // means we didn't set the value yet426427{428J9ROMClass *declaringClazz = J9_CLASS_FROM_METHOD(method)->romClass;429J9UTF8 * className = J9ROMCLASS_CLASSNAME(declaringClazz);430J9UTF8 * name = J9ROMMETHOD_NAME(romMethod);431if (J9UTF8_LENGTH(className) == 36432&& J9UTF8_LENGTH(name) == 21433&& 0==memcmp(utf8Data(className), "com/ibm/rmi/io/FastPathForCollocated", 36)434&& 0==memcmp(utf8Data(J9ROMMETHOD_NAME(romMethod)), "isVMDeepCopySupported", 21)435)436{437count = 0;438}439else if (J9UTF8_LENGTH(className) == 39440&& J9UTF8_LENGTH(name) == 9441&& 0 == memcmp(utf8Data(className), "java/util/concurrent/ThreadPoolExecutor", 39)442&& 0 == memcmp(utf8Data(J9ROMMETHOD_NAME(romMethod)), "runWorker", 9)443)444{445count = 0;446}447else if (highCodeCacheOccupancyThresholdReached && !countInOptionSet && !TR::Options::getCountsAreProvidedByUser())448{449count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ?450TR::Options::getHighCodeCacheOccupancyBCount() :451TR::Options::getHighCodeCacheOccupancyCount();452}453else if (TR::Options::sharedClassCache())454{455// The default FE may not have TR_J9SharedCache object because the FE may have456// been created before options were processed.457TR_J9VMBase *fej9 = TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM);458TR_J9SharedCache *sc = fej9 ? fej9->sharedCache() : NULL;459#if defined(J9VM_INTERP_AOT_COMPILE_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))460if (sc && sc->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass))461{462PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);463I_64 sharedQueryTime = 0;464if (optionsAOT->getOption(TR_EnableSharedCacheTiming))465sharedQueryTime = j9time_hires_clock(); // may not be good for SMP466467if (jitConfig->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, romMethod))468{469int32_t scount = optionsAOT->getInitialSCount();470uint16_t newScount = 0;471if (sc && sc->isHint(method, TR_HintFailedValidation, &newScount))472{473if ((scount == TR_QUICKSTART_INITIAL_SCOUNT) || (scount == TR_INITIAL_SCOUNT))474{ // If scount is not user specified (coarse way due to info being lost from options parsing)475// TODO: Is casting the best thing to do here?476scount= std::min(getCount(romMethod, optionsJIT, optionsAOT), static_cast<int32_t>(newScount) ); // Find what would've been normal count for this method and477// make sure new scount isn't larger than that478if (optionsAOT->getVerboseOption(TR_VerboseSCHints) || optionsJIT->getVerboseOption(TR_VerboseSCHints))479TR_VerboseLog::writeLineLocked(TR_Vlog_SCHINTS,"Found hint in sc, increase scount to: %d, wanted scount: %d", scount, newScount);480}481}482count = scount;483compInfo->incrementNumMethodsFoundInSharedCache();484}485// AOT Body not in SCC, so scount was not set486else if (!TR::Options::getCountsAreProvidedByUser() && !countInOptionSet)487{488bool useLowerCountsForAOTCold = false;489if (TR::Options::getCmdLineOptions()->getOption(TR_LowerCountsForAotCold) && compInfo->isWarmSCC() == TR_no)490{491// Because C-interpreter is slower we need to rely more on jitted code492// This means compiling more, but we have to be careful.493// Let's use some smaller than normal counts in the cold run (to avoid494// extra compilations in the warm runs), but only if495//496// 1) The Default SCC isn't used - because we don't want to increase footprint497//498// OR499//500// 1) Quickstart - because we don't risk losing iprofiling info501// 2) GracePeriod - because we want to limit the number of 'extra'502// compilations and short apps are affected more503// 3) Bootstrap - same as above, plus if these methods get into the504// SCC I would rather have non-app specific methods505//506// The danger is that very small applications that don't even get to AOT 200 methods507// may think that the runs are always cold508509510// J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES is a good proxy for whether the511// Default SCC is set because, when -Xshareclasses option is used, by default non512// bootstrap loaded classes are put into the SCC. However, if the -Xshareclasses513// option isn't used, then the Default SCC only contains bootstrap loaded classes.514if (J9_SHARED_CACHE_DEFAULT_BOOT_SHARING(jitConfig->javaVM) &&515J9_ARE_ALL_BITS_SET(jitConfig->javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES))516{517useLowerCountsForAOTCold = true;518}519else if (compInfo->getPersistentInfo()->getElapsedTime() <= (uint64_t)compInfo->getPersistentInfo()->getClassLoadingPhaseGracePeriod() &&520TR::Options::isQuickstartDetected() &&521fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method))522{523useLowerCountsForAOTCold = true;524}525}526527if (useLowerCountsForAOTCold)528{529// TODO: modify the function that reads a specified count such that530// if the user specifies a count or bcount on the command line that is obeyed531// and we don't try the following line532count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ?533std::min(optionsJIT->getInitialColdRunBCount(), optionsAOT->getInitialColdRunBCount()) :534std::min(optionsJIT->getInitialColdRunCount(), optionsAOT->getInitialColdRunCount());535}536// Increase counts for methods from non-bootstrap classes to improve throughput537else if (TR::Options::getCmdLineOptions()->getOption(TR_IncreaseCountsForNonBootstrapMethods))538{539if (!fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method))540count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;541}542// We may lower or increase the counts based on TR_HintMethodCompiledDuringStartup543if (count == -1 && // Not yet changed544jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&545(TR_HintMethodCompiledDuringStartup & TR::Options::getAOTCmdLineOptions()->getEnableSCHintFlags()) && sc)546{547bool wasCompiledDuringStartup = sc->isHint(method, TR_HintMethodCompiledDuringStartup);548if (wasCompiledDuringStartup)549{550// Lower the counts for any method that doesn't have an AOT body,551// but we know it has been compiled in previous runs.552if (TR::Options::getCmdLineOptions()->getOption(TR_ReduceCountsForMethodsCompiledDuringStartup))553count = TR::Options::getCountForMethodsCompiledDuringStartup();554}555else // method was not compiled during startup556{557if (TR::Options::getCmdLineOptions()->getOption(TR_IncreaseCountsForMethodsCompiledOutsideStartup) &&558TR::Options::startupTimeMatters() == TR_maybe) // For TR_no the counts are already high, for TR_yes we cannot get in here559count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;560}561}562}563if (optionsAOT->getOption(TR_EnableSharedCacheTiming))564{565sharedQueryTime = j9time_hires_delta(sharedQueryTime, j9time_hires_clock(), J9PORT_TIME_DELTA_IN_MICROSECONDS);566compInfo->setAotQueryTime(compInfo->getAotQueryTime() + (UDATA)sharedQueryTime);567}568}569else // ROM class not in shared class cache570{571#if !defined(J9ZOS390) // Do not change the counts on zos at the moment since the572// shared cache capacity is higher on this platform and by573// increasing counts we could end up significantly impacting startup574if (TR::Options::getCmdLineOptions()->getOption(TR_UseHigherCountsForNonSCCMethods))575count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;576#endif // !J9ZOS390577}578#endif // defined(J9VM_INTERP_AOT_COMPILE_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))579} // if (TR::Options::sharedClassCache())580if (count == -1) // count didn't change yet581{582if (!TR::Options::getCountsAreProvidedByUser() &&583fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method))584count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR::Options::getCountForLoopyBootstrapMethods() : TR::Options::getCountForLooplessBootstrapMethods();585if (count == -1)586count = getCount(romMethod, optionsJIT, optionsAOT);587588// If add-spreading-invocation mode is enabled, add a hash value (hashed from method name) to count589if (optionsAOT->getOption(TR_EnableCompilationSpreading) || optionsJIT->getOption(TR_EnableCompilationSpreading))590{591count += initializeSendTargetHelperFuncHashValueForSpreading(method);592}593else if (TR::Options::getCmdLineOptions()->getOption(TR_EnableEarlyCompilationDuringIdleCpu))594{595// Set only a fraction of a count to accelerate compilations596if (count > 20)597count = count * TR::Options::_countPercentageForEarlyCompilation / 100;598// TODO: disable this mechanism after an hour or so to conserve idle time599}600}601}602603// Option to display chosen counts to track possible bugs604if (optionsJIT->getVerboseOption(TR_VerboseCounts))605{606char buffer[500];607fe->printTruncatedSignature(buffer, 500, (TR_OpaqueMethodBlock *) method);608TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Setting count=%d for %s", count, buffer);609}610611TR::CompilationInfo::setInitialInvocationCountUnsynchronized(method,count);612613if (TR::Options::getJITCmdLineOptions()->getOption(TR_DumpInitialMethodNamesAndCounts) || TR::Options::getAOTCmdLineOptions()->getOption(TR_DumpInitialMethodNamesAndCounts))614{615bool containsInfo = sharedCacheContainsProfilingInfoForMethod(vmThread, compInfo, romMethod);616char buf[3072];617J9UTF8 * className = J9ROMCLASS_CLASSNAME(J9_CLASS_FROM_METHOD(method)->romClass);618J9UTF8 * name = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(method));619J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(method));620int32_t sigLen = sprintf(buf, "%.*s.%.*s%.*s", J9UTF8_LENGTH(className), utf8Data(className), J9UTF8_LENGTH(name), utf8Data(name), J9UTF8_LENGTH(signature), utf8Data(signature));621printf("Initial: Signature %s Count %d isLoopy %d isAOT %" OMR_PRIuPTR " is in SCC %d SCCContainsProfilingInfo %d \n",buf,TR::CompilationInfo::getInvocationCount(method),J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod),622TR::Options::sharedClassCache() ? jitConfig->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, romMethod) : 0,623TR::Options::sharedClassCache() ? TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM)->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass) : 0,containsInfo) ; fflush(stdout);624}625}626627#if defined(J9VM_INTERP_PROFILING_BYTECODES)628629static int32_t interpreterProfilingState = IPROFILING_STATE_OFF;630static int32_t interpreterProfilingRecordsCount = 0; // reset when state changes to IPROFILING_STATE_GOING_OFF631static int32_t interpreterProfilingJITSamples = 0;632static int32_t interpreterProfilingINTSamples = 0;633static int32_t interpreterProfilingMonitoringWindow = 0;634static bool interpreterProfilingWasOnAtStartup = false;635636/**637* J9 VM hook, called when the profiling bytecode buffer is full.638*/639static void jitHookBytecodeProfiling(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData);640641static void turnOnInterpreterProfiling(J9JavaVM* javaVM, TR::CompilationInfo * compInfo)642{643if (interpreterProfilingState == IPROFILING_STATE_OFF)644{645TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(javaVM->jitConfig, 0));646TR_IProfiler *iProfiler = vmj9->getIProfiler();647648if (iProfiler->getProfilerMemoryFootprint() >= TR::Options::_iProfilerMemoryConsumptionLimit)649return;650651J9HookInterface ** hook = javaVM->internalVMFunctions->getVMHookInterface(javaVM);652653interpreterProfilingRecordsCount = 0;654interpreterProfilingState = IPROFILING_STATE_ON;655interpreterProfilingJITSamples = 0;656657PORT_ACCESS_FROM_JAVAVM(javaVM);658659660if ((*hook)->J9HookRegisterWithCallSite(hook, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, OMR_GET_CALLSITE(), NULL))661{662j9tty_printf(PORTLIB, "Error: Unable to install J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL listener\n");663return;664}665else666{667if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))668{669TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler reactivated...", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime());670}671}672}673}674#endif675676#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)677static TR_YesNoMaybe shouldInitiateDLT(J9DLTInformationBlock *dltInfo, int32_t idx, bool *bcRepeats, int32_t *hitCnt)678{679static int32_t triggerCount = -1;680681if (triggerCount == -1)682{683static char *envTrigger = feGetEnv("TR_DLTcount");684if (envTrigger == NULL)685{686triggerCount = 3;687}688else689triggerCount = atoi(envTrigger);690}691692*bcRepeats = false;693*hitCnt = -1; // -1 means unknown694695if (triggerCount <= 1)696return TR_yes;697698J9Method *currentMethod = dltInfo->methods[idx];699int32_t hitCount=0, loopCnt=0, bcIdx = dltInfo->bcIndex[idx];700701idx = (idx==0)?(J9DLT_HISTORY_SIZE-1):(idx-1);702703while (loopCnt < J9DLT_HISTORY_SIZE-1)704{705loopCnt++;706if (dltInfo->methods[idx] == currentMethod)707{708if (dltInfo->bcIndex[idx] >= bcIdx)709*bcRepeats = true;710hitCount++;711}712idx = (idx==0)?(J9DLT_HISTORY_SIZE-1):(idx-1);713if (loopCnt==triggerCount-1 && hitCount==triggerCount-1)714return TR_maybe;715}716717*hitCnt = hitCount;718if (hitCount>=triggerCount)719return TR_maybe;720721void *extra = TR::CompilationInfo::getPCIfCompiled(currentMethod);722if(extra && !TR::Options::getCmdLineOptions()->getOption(TR_DisableFastDLTOnLongRunningInterpreter))723{724TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(extra);725if (bodyInfo && bodyInfo->isLongRunningInterpreted())726return TR_yes;727}728729return TR_no;730}731732void *jitLookupDLT(J9VMThread *currentThread, J9Method *method, UDATA bcIndex)733{734J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;735736if (!jitConfig)737return 0;738739TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);740void *dltEntry = compInfo->searchForDLTRecord(method, bcIndex);741742if (!dltEntry)743return 0;744745J9DLTInformationBlock *dltBlock = &(currentThread->dltBlock);746dltBlock->dltSP = (uintptr_t)CONVERT_TO_RELATIVE_STACK_OFFSET(currentThread, currentThread->sp);747dltBlock->dltEntry = dltEntry;748return (void *)1;749}750751static UDATA dltTestIterator(J9VMThread * currentThread, J9StackWalkState * walkState)752{753switch(walkState->framesWalked)754{755case 1 :756if (((UDATA) walkState->pc <= J9SF_MAX_SPECIAL_FRAME_TYPE) || (walkState->pc == walkState->walkThread->javaVM->callInReturnPC))757return J9_STACKWALK_KEEP_ITERATING;758if (walkState->jitInfo!=NULL)759return J9_STACKWALK_STOP_ITERATING;760walkState->userData1 = (void *)1;761return J9_STACKWALK_STOP_ITERATING;762break;763764case 2 :765if (((UDATA) walkState->pc <= J9SF_MAX_SPECIAL_FRAME_TYPE) || (walkState->pc == walkState->walkThread->javaVM->callInReturnPC))766return J9_STACKWALK_STOP_ITERATING;767768if (walkState->jitInfo!=NULL)769return J9_STACKWALK_STOP_ITERATING;770771// We can stop at this point: candidate for sync transfer772walkState->userData1 = (void *)2;773return J9_STACKWALK_STOP_ITERATING;774break;775776case 3 : // unused currently777if (walkState->jitInfo!=NULL || ((UDATA) walkState->pc <= J9SF_MAX_SPECIAL_FRAME_TYPE) ||778(walkState->pc == walkState->walkThread->javaVM->callInReturnPC) || (*walkState->bp & J9SF_A0_INVISIBLE_TAG))779return J9_STACKWALK_STOP_ITERATING;780break;781}782783return J9_STACKWALK_KEEP_ITERATING;784}785786static void emptyJitGCMapCheck(J9VMThread * currentThread, J9StackWalkState * walkState, j9object_t * objectSlot, const void * stackLocation)787{788return;789}790791792static void jitGCMapCheck(J9VMThread* vmThread, IDATA handlerKey, void* userData)793{794795J9StackWalkState walkState;796walkState.flags = J9_STACKWALK_ITERATE_O_SLOTS | J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_CHECK_I_SLOTS_FOR_OBJECTS;797walkState.objectSlotWalkFunction = emptyJitGCMapCheck;798walkState.maxFrames = 2;799walkState.walkThread = vmThread;800walkState.userData1=0;801802static char *verbose = feGetEnv("TR_GCMapCheckVerbose");803if (verbose)804walkState.userData1 = (void*)((uintptr_t) walkState.userData1 | 1);805806static char *local = feGetEnv("TR_GCMapCheckLocalScavenge");807if (local)808walkState.userData1 = (void*)((uintptr_t) walkState.userData1 | 2);809810static char *global = feGetEnv("TR_GCMapCheckGlobalScavenge");811if (global)812walkState.userData1 = (void*)((uintptr_t) walkState.userData1 | 4);813814vmThread->javaVM->walkStackFrames(vmThread, &walkState);815816817return;818}819820void DLTLogic(J9VMThread* vmThread, TR::CompilationInfo *compInfo)821{822#define SIG_SZ 150823char sig[SIG_SZ];824if (!TR::Options::canJITCompile() ||825TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug) ||826TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicLoopTransfer) )827return;828if (TR::Options::_compilationDelayTime > 0 && // feature enabled829TR::Options::_compilationDelayTime > compInfo->getPersistentInfo()->getElapsedTime())830return;831832J9StackWalkState walkState;833walkState.maxFrames = 3;834walkState.userData1 = 0;835walkState.walkThread = vmThread;836walkState.frameWalkFunction = dltTestIterator;837walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_COUNT_SPECIFIED | J9_STACKWALK_SKIP_INLINES;838vmThread->javaVM->walkStackFrames(vmThread, &walkState);839uint8_t * startPC = 0;840if (walkState.userData1 == 0)841startPC = (uint8_t *)-1;842843J9DLTInformationBlock *dltBlock = &(vmThread->dltBlock);844int32_t idx = dltBlock->cursor + 1;845J9ROMMethod *romMethod = NULL;846bool bcRepeats;847void *extra = NULL;848849if (startPC!=(uint8_t *)-1 && walkState.method!=0)850romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState.method);851852idx = (idx==J9DLT_HISTORY_SIZE) ? 0 : idx;853dltBlock->cursor = idx;854if (startPC ||855walkState.method==0 ||856(romMethod->modifiers & J9AccNative) ||857((intptr_t)(walkState.method->constantPool) & J9_STARTPC_JNI_NATIVE) ||858!J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ||859TR::CompilationInfo::getJ9MethodVMExtra(walkState.method)==J9_JIT_NEVER_TRANSLATE ||860(J9CLASS_FLAGS(J9_CLASS_FROM_METHOD(walkState.method)) & J9AccClassHotSwappedOut) ||861walkState.bytecodePCOffset<=0) // FIXME: Deal with loop back on entry later862{863dltBlock->methods[idx] = 0;864return;865}866else867{868extra = TR::CompilationInfo::getPCIfCompiled(walkState.method);869if (extra)870{871TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(extra);872if (bodyInfo && bodyInfo->getMethodInfo()->hasFailedDLTCompRetrials())873{874dltBlock->methods[idx] = 0;875return;876}877}878}879880// Check whether we need a DLT compilation881bool doPerformDLT = false;882dltBlock->methods[idx] = walkState.method;883dltBlock->bcIndex[idx] = walkState.bytecodePCOffset;884TR_J9ByteCode bc = TR_J9ByteCodeIterator::convertOpCodeToByteCodeEnum(J9_BYTECODE_START_FROM_ROM_METHOD(romMethod)[walkState.bytecodePCOffset]);885if ((walkState.unwindSP - walkState.walkSP) == 0 && bc != J9BCinvokevirtual &&886bc != J9BCinvokespecial && bc != J9BCinvokestatic && bc != J9BCinvokeinterface &&887bc != J9BCinvokedynamic && bc != J9BCinvokehandle && bc != J9BCinvokehandlegeneric &&888bc != J9BCinvokespecialsplit && bc != J9BCinvokestaticsplit)889{890int32_t numHitsInDLTBuffer = -1;891TR_YesNoMaybe answer = shouldInitiateDLT(dltBlock, idx, &bcRepeats, &numHitsInDLTBuffer);892if (answer != TR_no)893{894// Perform another test895if (compInfo->getDLT_HT())896{897// If numHitsInDLTBuffer was not computed by shouldInitiateDLT do it now898if (numHitsInDLTBuffer == -1)899{900// Search again for number of hits901int32_t i = 0;902for (numHitsInDLTBuffer = 0; i < J9DLT_HISTORY_SIZE; i++)903if (dltBlock->methods[i] == walkState.method)904numHitsInDLTBuffer++;905}906// Check the DLT_HT907doPerformDLT = compInfo->getDLT_HT()->shouldIssueDLTCompilation(walkState.method, numHitsInDLTBuffer);908}909else // DLT_HT is not allocated, so just issue the DLT request910{911doPerformDLT = true;912}913}914}915916if (doPerformDLT)917{918int32_t bcIndex = walkState.bytecodePCOffset;919J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;920TR_J9VMBase * vm = TR_J9VMBase::get(jitConfig, vmThread);921922static char *enableDebugDLT = feGetEnv("TR_DebugDLT");923bool dltMostOnce = false;924int32_t enableDLTidx = -1;925int32_t disableDLTidx = -1;926int32_t dltOptLevel = -1;927928if (enableDebugDLT!=NULL)929{930TR::OptionSet *optionSet = findOptionSet(walkState.method, false);931TR::Options *options = optionSet ? optionSet->getOptions() : NULL;932933enableDLTidx = options ? options->getEnableDLTBytecodeIndex() : -1;934disableDLTidx = options ? options->getDisableDLTBytecodeIndex() : -1;935936if (enableDLTidx != -1)937{938J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState.method);939bcIndex = enableDLTidx;940if (enableDLTidx >= (J9_BYTECODE_END_FROM_ROM_METHOD(romMethod)) - (J9_BYTECODE_START_FROM_ROM_METHOD(romMethod)))941return;942dltBlock->bcIndex[idx] = enableDLTidx;943}944if (disableDLTidx != -1 && disableDLTidx == bcIndex) return;945946dltMostOnce = options ? options->getOption(TR_DLTMostOnce) :947TR::Options::getCmdLineOptions()->getOption(TR_DLTMostOnce);948dltOptLevel = options ? options->getDLTOptLevel() :949TR::Options::getCmdLineOptions()->getDLTOptLevel();950}951952// This setup is for matching dltEntry to the right transfer point. It can be an issue only953// in rare situations where Java code is executed for asyncEvents, leading to recursive DLT.954dltBlock->dltSP = (uintptr_t)CONVERT_TO_RELATIVE_STACK_OFFSET(vmThread, vmThread->sp);955956dltBlock->dltEntry = compInfo->searchForDLTRecord(dltBlock->methods[idx], bcIndex);957if (dltBlock->dltEntry != NULL)958return;959960static char *TR_DLTmostOnce = feGetEnv("TR_DLTmostOnce");961if (TR_DLTmostOnce != NULL || dltMostOnce)962{963if (compInfo->searchForDLTRecord(dltBlock->methods[idx], -1))964return;965}966967static char *TR_DLTforcedHot = feGetEnv("TR_DLTforcedHot");968static char *TR_DLTforcedCold = feGetEnv("TR_DLTforcedCold"); // Usage error: set both969TR_OptimizationPlan *plan = NULL;970TR_CompilationErrorCode eCode;971bool queued = false;972973974// TODO: add an event for the controller to decide what to do975TR_Hotness optLevel = warm;976// decide if we are going to compile this method to hot977if (dltOptLevel != -1)978{979optLevel = (TR_Hotness)dltOptLevel;980}981else if (TR_DLTforcedHot!=NULL)982{983optLevel = hot;984}985else if (TR_DLTforcedCold != NULL)986{987optLevel = cold;988}989else990{991bool systemClass = vm->isClassLibraryMethod((TR_OpaqueMethodBlock*)walkState.method);992if (systemClass)993{994optLevel = cold;995//return;996}997else // userClass998{999// DLTs cannot be very important for large apps, so use cold compilations1000if (compInfo->getPersistentInfo()->getNumLoadedClasses() >= TR::Options::_bigAppThreshold)1001{1002optLevel = cold;1003}1004else1005{1006bool classLoadPhase = compInfo->getPersistentInfo()->isClassLoadingPhase();1007if (bcRepeats)1008{1009if (!classLoadPhase)1010optLevel = hot;1011}1012else1013{1014if (classLoadPhase)1015optLevel = cold;1016}1017}1018}1019}10201021plan = TR_OptimizationPlan::alloc(optLevel);1022if (!plan)1023return;10241025if (vm->isLogSamplingSet())1026{1027vm->printTruncatedSignature(sig, SIG_SZ, (TR_OpaqueMethodBlock*)walkState.method);1028TR_VerboseLog::writeLineLocked(TR_Vlog_DLT,"Will try to queue DLT compilation for %s bcIndex=%d", sig, bcIndex);1029}10301031// Issue a DLT compilation request (scope for compilation request)1032{1033J9::MethodInProgressDetails details(walkState.method, dltBlock->bcIndex[dltBlock->cursor]);1034dltBlock->dltEntry = compInfo->compileMethod(vmThread, details, 0, TR_maybe, &eCode, &queued, plan);1035}10361037if (walkState.userData1==(void *)2 && dltBlock->dltEntry) // Cannot transfer synchronously1038dltBlock->dltEntry = NULL;10391040for (idx=0; idx<J9DLT_HISTORY_SIZE; idx++)1041if (dltBlock->methods[idx] == walkState.method)1042dltBlock->methods[idx] = 0;10431044if (!queued)1045{1046// plan must exist because we checked above1047TR_OptimizationPlan::freeOptimizationPlan(plan);1048}1049else // DLT request has been queued1050{1051// Create a request for normal JIT compilation as well1052J9Method *j9method = walkState.method;1053if (!TR::CompilationInfo::isCompiled(j9method))1054{1055// No need to check for j9method->extra != (void*)J9_JIT_QUEUED_FOR_COMPILATION1056// because we check the count value below1057int32_t count = TR::CompilationInfo::getInvocationCount(j9method);1058if (count > 0)1059{1060// Change the count to 0 as if this interpreted method got a sample1061if (TR::CompilationInfo::setInvocationCount(j9method, count, 0))1062{1063if (vm->isLogSamplingSet())1064{1065TR_VerboseLog::writeLineLocked(TR_Vlog_DLT,"side-effect: reducing count to 0 for %s", sig);1066}1067if (vm->isAsyncCompilation())1068{1069TR_MethodEvent event;1070event._eventType = TR_MethodEvent::JitCompilationInducedByDLT;1071event._j9method = j9method;1072event._oldStartPC = 0;1073event._vmThread = vmThread;1074event._classNeedingThunk = 0;1075bool newPlanCreated;1076TR_OptimizationPlan *jitplan = TR::CompilationController::getCompilationStrategy()->processEvent(&event, &newPlanCreated);1077if (jitplan)1078{1079bool queued1 = false;1080vm->startAsyncCompile((TR_OpaqueMethodBlock *) j9method, 0, &queued1, jitplan);1081if (!queued1 && newPlanCreated)1082TR_OptimizationPlan::freeOptimizationPlan(jitplan);1083}1084}1085}1086}1087}1088}1089}1090} // DLTLogic10911092#endif10931094/**1095* Stack frame iterator. Causes a tracepoint to be triggered for each frame.1096*1097* Returns:1098* J9_STACKWALK_KEEP_ITERATING1099* J9_STACKWALK_STOP_ITERATING1100*/1101static UDATA1102walkStackIterator(J9VMThread *currentThread, J9StackWalkState *walkState)1103{1104if(walkState->userData1 == 0)1105{1106Trc_JIT_MethodSampleStart(currentThread, walkState->method, walkState->pc, walkState->jitInfo);1107walkState->userData1 = (void *) 1;1108}1109else1110{1111Trc_JIT_MethodSampleContinue(currentThread, walkState->method, walkState->pc, walkState->jitInfo);1112}1113return J9_STACKWALK_KEEP_ITERATING;1114}11151116static void walkStackForSampling(J9VMThread *vmThread)1117{1118J9StackWalkState walkState;11191120walkState.userData1 = 0;1121walkState.walkThread = vmThread;1122walkState.skipCount = 0;1123walkState.maxFrames = 32; // TODO arbitrary, will become a settable property1124walkState.flags = J9_STACKWALK_VISIBLE_ONLY |1125J9_STACKWALK_INCLUDE_NATIVES |1126J9_STACKWALK_ITERATE_FRAMES;1127walkState.frameWalkFunction = walkStackIterator;11281129if (vmThread->javaVM->walkStackFrames(vmThread, &walkState) != J9_STACKWALK_RC_NONE)1130{1131Trc_JIT_MethodSampleFail(vmThread, 0);1132}1133}11341135/**1136* Stack frame iterator (reduced version). Causes a tracepoint to be triggered for each frame.1137* Only sends the method name.1138* Every time tries to walk two frames (sample two methods) and send them out together.1139*1140* Returns:1141* J9_STACKWALK_KEEP_ITERATING1142* J9_STACKWALK_STOP_ITERATING1143*/1144static UDATA1145walkStackIteratorReduced(J9VMThread *currentThread, J9StackWalkState *walkState)1146{1147if(walkState->userData1 == 0)1148{1149Trc_JIT_MethodSampleStart1(currentThread, walkState->method);1150walkState->userData1 = (void *) 1;1151}1152else if(walkState->userData2 == 0)1153{1154// userData2 is used as the cache. If userData2 is NULL, the current method will be stored in userData2 temporarily1155walkState->userData2 = (void *) walkState->method;1156}1157else1158{1159// userData2 is used as the cache. If userData2 is nonempty, the previously stored method (in userData2)1160// and the current method will be sent out together, then userData2 will be cleared.1161Trc_JIT_MethodSampleContinue2(currentThread, (J9Method*) walkState->userData2, walkState->method);1162walkState->userData2 = (void *) 0;1163}1164return J9_STACKWALK_KEEP_ITERATING;1165}11661167static void walkStackForSamplingReduced(J9VMThread *vmThread)1168{1169J9StackWalkState walkState;11701171walkState.userData1 = 0;1172walkState.userData2 = 0;1173walkState.walkThread = vmThread;1174walkState.skipCount = 0;1175walkState.maxFrames = 32; // TODO arbitrary, will become a settable property1176walkState.flags = J9_STACKWALK_VISIBLE_ONLY |1177J9_STACKWALK_INCLUDE_NATIVES |1178J9_STACKWALK_ITERATE_FRAMES;1179walkState.frameWalkFunction = walkStackIteratorReduced;11801181if (vmThread->javaVM->walkStackFrames(vmThread, &walkState) != J9_STACKWALK_RC_NONE)1182{1183Trc_JIT_MethodSampleFail(vmThread, 0);1184}1185else if(walkState.userData2 != 0)1186{1187// If there is one last method left in userData2, send it out.1188Trc_JIT_MethodSampleContinue1(vmThread, (J9Method*) walkState.userData2);1189walkState.userData2 = (void *) 0;1190}1191}11921193inline static bool tryAndProcessBuffers(J9VMThread *vmThread, TR_J9VMBase *vm, TR_HWProfiler *hwProfiler)1194{1195bool canEnableRI = false;1196if (hwProfiler->getProcessBufferState() >= 0)1197{1198if (vm->_hwProfilerShouldNotProcessBuffers)1199{1200vm->_hwProfilerShouldNotProcessBuffers--;1201}1202else1203{1204vm->_hwProfilerShouldNotProcessBuffers = TR::Options::_hwProfilerRIBufferProcessingFrequency;1205canEnableRI = hwProfiler->processBuffers(vmThread, vm);1206}1207}1208return canEnableRI;1209}12101211static void processHWPBuffer(J9VMThread *vmThread, TR_J9VMBase *vm)1212{1213TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);1214if (!compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())1215return; // Nothing to do in a RI disabled environment12161217TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();12181219if (hwProfiler->isExpired())1220{1221if (IS_THREAD_RI_INITIALIZED(vmThread))1222{1223if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler))1224{1225TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Thread %p will be de-initialized for RI because RI expiration time was reached", vmThread);1226}1227hwProfiler->deinitializeThread(vmThread);1228}1229}1230else if (hwProfiler->getProcessBufferState() >= 0 && // avoid overhead if RI is off1231hwProfiler->isHWProfilingAvailable(vmThread))1232{1233bool threadInitialized = false;1234// HW Available, but thread not initialized.1235if (!IS_THREAD_RI_INITIALIZED(vmThread))1236threadInitialized = hwProfiler->initializeThread(vmThread);1237else1238threadInitialized = true;12391240bool canUseStartUsingRI = (!TR::Options::getCmdLineOptions()->getOption(TR_DisableHardwareProfilerDuringStartup)1241|| vmThread->javaVM->phase == J9VM_PHASE_NOT_STARTUP);12421243// If RI is enabled, poll buffer to swap.1244if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableHWProfilerDataCollection)1245&& threadInitialized1246&& canUseStartUsingRI)1247{1248if (IS_THREAD_RI_ENABLED(vmThread))1249{1250tryAndProcessBuffers(vmThread, vm, hwProfiler);1251}1252#ifdef J9VM_JIT_RUNTIME_INSTRUMENTATION1253else1254{1255PORT_ACCESS_FROM_VMC(vmThread);1256if (tryAndProcessBuffers(vmThread, vm, hwProfiler))1257{1258j9ri_enable(vmThread->riParameters);1259if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler))1260TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "RI is enabled for vmThread 0x%p", vmThread);1261}1262}1263#endif1264}1265}1266}12671268static void jitMethodSampleInterrupt(J9VMThread* vmThread, IDATA handlerKey, void* userData)1269{1270J9StackWalkState walkState;12711272walkState.flags = J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_COUNT_SPECIFIED;1273walkState.skipCount = 0;1274walkState.maxFrames = 1;1275walkState.walkThread = vmThread;1276vmThread->javaVM->walkStackFrames(vmThread, &walkState);1277if (walkState.framesWalked == 0)1278return;12791280J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;1281if (jitConfig == 0)1282return; // if a hook gets called after freeJitConfig then not much else we can do12831284TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);12851286TR_J9VMBase * vm = TR_J9VMBase::get(jitConfig, vmThread);12871288// Runtime Instrumentation1289processHWPBuffer(vmThread, vm);12901291if ((jitConfig->runtimeFlags & J9JIT_DEFER_JIT) == 0) // Reject any samples if we decided to postpone jitting1292{1293uint8_t * startPC = 0;1294int32_t codeSize = 0;1295TR_MethodMetaData * metaData = (TR_MethodMetaData *)walkState.jitInfo;1296if (metaData)1297{1298startPC = (uint8_t*)metaData->startPC;1299codeSize = compInfo->calculateCodeSize(metaData);1300}13011302#if defined(J9VM_INTERP_PROFILING_BYTECODES)1303if (interpreterProfilingState != IPROFILING_STATE_OFF &&1304!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))1305{1306if (startPC)1307interpreterProfilingJITSamples ++;1308else1309interpreterProfilingINTSamples ++;1310}13111312if (interpreterProfilingState == IPROFILING_STATE_OFF &&1313!startPC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))1314{1315interpreterProfilingINTSamples++;1316}1317#endif1318if (startPC)1319compInfo->_intervalStats._compiledMethodSamples++;1320else1321compInfo->_intervalStats._interpretedMethodSamples++;1322compInfo->getPersistentInfo()->incJitTotalSampleCount();13231324#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)1325DLTLogic(vmThread, compInfo);1326#endif13271328if(TrcEnabled_Trc_JIT_MethodSampleStart1)1329{1330walkStackForSamplingReduced(vmThread);1331}1332else if(TrcEnabled_Trc_JIT_MethodSampleStart)1333{1334walkStackForSampling(vmThread);1335}13361337#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)1338if (!TR::Options::getCmdLineOptions()->getOption(TR_MimicInterpreterFrameShape) &&1339!compInfo->getPersistentInfo()->getDisableFurtherCompilation())1340{1341static char *enableDebugDLT = feGetEnv("TR_DebugDLT");1342static J9Method *skipDLTMethod = NULL;1343bool skipSampleMethod = false;13441345/* Code to support disableCompilationAfterDLT option:1346* If env var TR_DebugDLT & option disableCompilationAfterDLT1347* is used, do not allow sampling interrupt to queue a standard1348* compilation for any method that has already been DLT compiled.1349*1350* A static J9Method pointer is used to avoid incurring the overhead1351* of finding option sets as much as possible.1352*/1353if (enableDebugDLT != NULL && compInfo->searchForDLTRecord(walkState.method, -1) != NULL)1354{1355if (skipDLTMethod==walkState.method)1356{1357skipSampleMethod = true;1358}1359else if (TR::Options::getCmdLineOptions()->getOption(TR_DisableCompilationAfterDLT))1360{1361skipDLTMethod = walkState.method;1362skipSampleMethod = true;1363}1364else1365{1366TR::OptionSet *optionSet = findOptionSet(walkState.method, false);1367if (optionSet != NULL &&1368optionSet->getOptions() != NULL &&1369optionSet->getOptions()->getOption(TR_DisableCompilationAfterDLT))1370{1371skipDLTMethod = walkState.method;1372skipSampleMethod = true;1373}1374}1375}1376/* If TR_DebugDLT env var is not used, no DLT has been done1377* for this method, or the disableCompilationAfterDLT option was not1378* used for the method, then queue a compilation with sampleMethod()1379*/1380if (!skipSampleMethod)1381TR::Recompilation::sampleMethod(vmThread, vm, startPC, codeSize, walkState.pc, walkState.method, jitConfig->samplingTickCount);1382}1383#else // !J9VM_JIT_DYNAMIC_LOOP_TRANSFER1384if (!TR::Options::getCmdLineOptions()->getOption(TR_MimicInterpreterFrameShape) &&1385!compInfo->getPersistentInfo()->getDisableFurtherCompilation())1386{1387TR::Recompilation::sampleMethod(vmThread, vm, startPC, codeSize, walkState.pc, walkState.method, jitConfig->samplingTickCount);1388}1389#endif1390}1391}13921393#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)1394static void jitHookClassesUnloadEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1395{1396}1397#endif13981399typedef struct J9JitPrivateThreadData{1400U_8 numberOfFrames;1401U_8 numberOfBuffers;1402U_8 frameCount;1403int index;1404U_8 * pcList[1];1405}J9JitPrivateThreadData;14061407/**1408* Collect jitted stack frames during GC stack walks to help with debugging GC map PMRs.1409*1410* CAUTION walkThread is the thread doing the walking - usually a GC worker thread. It is not1411* the thread we want to use to find the appropriate buffer to update. For that we need to look1412* in walkState->walkThread. The walkThread parameter seems to be unnecessary.1413*/1414static UDATA collectJitPrivateThreadData(J9VMThread * walkThread, J9StackWalkState * walkState)1415{1416J9JitPrivateThreadData * jitData = NULL;1417J9VMThread * threadBeingWalked = walkState->walkThread;1418if (threadBeingWalked)1419jitData = (J9JitPrivateThreadData *)threadBeingWalked->jitPrivateData;14201421if(NULL != walkState->jitInfo && jitData && (jitData->frameCount < (jitData->numberOfFrames-1) ))1422{1423jitData->pcList[jitData->index] = walkState->pc;1424jitData->frameCount++;1425jitData->index = (jitData->index+1);1426}14271428return J9_STACKWALK_KEEP_ITERATING;1429}14301431void finalizeJitPrivateThreadData(J9VMThread * currentThread)1432{1433J9VMThread *thread = currentThread;1434J9JitPrivateThreadData * jitData;1435do1436{1437if(thread->jitPrivateData)1438{1439jitData= (J9JitPrivateThreadData *)thread->jitPrivateData;1440while(jitData->index%jitData->numberOfFrames!=0 && jitData->index <(jitData->numberOfFrames)*(jitData->numberOfBuffers))1441{1442jitData->pcList[jitData->index]=0;1443jitData->index = (jitData->index+1)%((jitData->numberOfFrames)*(jitData->numberOfBuffers));1444}1445jitData->frameCount=0;1446}1447thread = thread->linkNext;1448}1449while (thread &&(thread != currentThread));1450}14511452void initJitPrivateThreadData(J9VMThread * currentThread)1453{1454if(!currentThread->javaVM->collectJitPrivateThreadData)1455{1456currentThread->javaVM->collectJitPrivateThreadData = &collectJitPrivateThreadData;1457}1458J9VMThread *thread = currentThread;1459J9JitPrivateThreadData * jitData;1460do1461{1462if(thread->jitPrivateData)1463{1464jitData= (J9JitPrivateThreadData *)thread->jitPrivateData;1465while(jitData->index%jitData->numberOfFrames!=0 && jitData->index <(jitData->numberOfFrames)*(jitData->numberOfBuffers))1466{1467jitData->pcList[jitData->index]=0;1468jitData->index = (jitData->index+1)%((jitData->numberOfFrames)*(jitData->numberOfBuffers));1469}14701471if(jitData->frameCount!=0)1472{1473if(jitData->index!=0)1474jitData->pcList[jitData->index-1] =(U_8*) 1;1475else1476jitData->pcList[jitData->numberOfFrames*jitData->numberOfBuffers-1] = (U_8*)1;1477}14781479jitData->frameCount=0;1480}1481thread = thread->linkNext;1482}1483while (thread &&(thread != currentThread));1484}14851486static void jitHookGlobalGCStart(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1487{1488J9VMThread* vmThread = (J9VMThread*)((MM_GlobalGCStartEvent *)eventData)->currentThread->_language_vmthread;1489J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;14901491if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())1492initJitPrivateThreadData(vmThread);14931494if (jitConfig && jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)1495printf("\n{GGC");1496jitReclaimMarkedAssumptions(false);1497}14981499static void jitHookLocalGCStart(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1500{1501MM_LocalGCStartEvent * localGCStartEventData = (MM_LocalGCStartEvent *)eventData;1502J9VMThread * vmThread = (J9VMThread *)localGCStartEventData->currentThread->_language_vmthread;1503J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;15041505if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())1506initJitPrivateThreadData(vmThread);15071508if (jitConfig == 0)1509return; // if a hook gets called after freeJitConfig then not much else we can do15101511if (jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)1512printf("\n{Scavenge");15131514if (jitConfig->gcTraceThreshold && jitConfig->gcCount == jitConfig->gcTraceThreshold)1515{1516printf("\n<jit: enabling stack tracing at gc %" OMR_PRIuPTR ">", jitConfig->gcCount);1517TR::Options::getCmdLineOptions()->setVerboseOption(TR_VerboseGc);1518}1519jitReclaimMarkedAssumptions(false);1520}15211522static void jitHookGlobalGCEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1523{1524J9VMThread* vmThread = (J9VMThread*)((MM_GlobalGCStartEvent *)eventData)->currentThread->_language_vmthread;1525J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;15261527if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())1528finalizeJitPrivateThreadData(vmThread);15291530if (jitConfig == 0)1531return; // if a hook gets called after freeJitConfig then not much else we can do15321533TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);15341535getOutOfIdleStatesUnlocked(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "GC");15361537TR::CodeCacheManager::instance()->synchronizeTrampolines();1538if (jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)1539printf("}");15401541}15421543static void jitHookLocalGCEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1544{1545J9VMThread * vmThread = (J9VMThread *) ((MM_LocalGCEndEvent *)eventData)->currentThread->_language_vmthread;1546J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;15471548if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())1549finalizeJitPrivateThreadData(vmThread);15501551if (jitConfig == 0)1552return; // if a hook gets called after freeJitConfig then not much else we can do15531554if (jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)1555printf("}");1556}15571558static void initThreadAfterCreation(J9VMThread *vmThread)1559{1560J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;1561if (jitConfig == 0)1562return; // if a hook gets called after freeJitConfig then not much else we can do15631564if (TR::Options::getCmdLineOptions()->getOption(TR_EnableValueTracing))1565{1566PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);15671568TR_JitPrivateConfig *pJitConfig = (TR_JitPrivateConfig *)jitConfig->privateConfig;15691570if (pJitConfig)1571{1572int32_t size = pJitConfig->maxRuntimeTraceBufferSizeInBytes;1573UDATA buffer = (UDATA)j9mem_allocate_memory(size, J9MEM_CATEGORY_JIT);1574if (!buffer)1575return;15761577VMTHREAD_TRACINGBUFFER_CURSOR(vmThread) = buffer;15781579// Leave some headroom at the top of each buffer.1580//1581VMTHREAD_TRACINGBUFFER_TOP(vmThread) = buffer + size - pJitConfig->maxTraceBufferEntrySizeInBytes;15821583// Create a tracing file handle and prepare the file for writing.1584//1585char fileName[64];1586IDATA tracefp= -1;15871588sprintf(fileName, "%s_" POINTER_PRINTF_FORMAT, pJitConfig->itraceFileNamePrefix, vmThread);15891590if ((tracefp = j9file_open(fileName, EsOpenWrite | EsOpenAppend | EsOpenCreate, 0644)) == -1)1591{1592j9tty_err_printf(PORTLIB, "Error: Failed to open jit trace file %s.\n", fileName);1593}15941595VMTHREAD_TRACINGBUFFER_FH(vmThread) = tracefp;1596}1597}15981599#if defined(TR_HOST_S390)1600vmThread->codertTOC = (void *)jitConfig->pseudoTOC;1601#endif16021603if (TR::Options::getCmdLineOptions()->getOption(TR_CountWriteBarriersRT))1604{1605vmThread->debugEventData6 = 0;1606vmThread->debugEventData7 = 0;1607}16081609TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);1610#if defined(ENABLE_GPU)1611extern void *initGPUThread(J9VMThread *vmThread, TR::PersistentInfo *persistentInfo);1612initGPUThread(vmThread, compInfo->getPersistentInfo());1613#endif1614getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "thread creation");16151616if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableSamplingJProfiling))1617{1618uint8_t jitState = compInfo->getPersistentInfo()->getJitState();1619if (jitState == IDLE_STATE || jitState == STARTUP_STATE)1620vmThread->debugEventData4 = 1;1621else1622vmThread->debugEventData4 = 1;1623}16241625vmThread->jitCountDelta = 2; // by default we assume there are compilation threads active1626if (compInfo)1627{1628compInfo->acquireCompMonitor(vmThread);1629if (compInfo->getNumUsableCompilationThreads() > 0 && compInfo->getNumCompThreadsActive() == 0)1630{1631vmThread->jitCountDelta = 0;1632}1633compInfo->releaseCompMonitor(vmThread);16341635vmThread->maxProfilingCount = (UDATA)encodeCount(compInfo->getIprofilerMaxCount());1636}16371638U_8 numberOfBuffers,numberOfFrames;1639if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() <= 255)1640numberOfBuffers=TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers();1641else1642numberOfBuffers=255;16431644if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames() <= 254)1645numberOfFrames=TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames();1646else1647numberOfFrames=254;16481649if(!vmThread->jitPrivateData && numberOfFrames && numberOfBuffers)1650{1651numberOfFrames++;1652vmThread->jitPrivateData = (J9JitPrivateThreadData *) TR_Memory::jitPersistentAlloc(sizeof(J9JitPrivateThreadData)+(numberOfFrames*numberOfBuffers -1)*sizeof(U_8*));1653J9JitPrivateThreadData * jitData= (J9JitPrivateThreadData *)vmThread->jitPrivateData;1654//199878 : jitPersistentAlloc may return NULL and this extra diagnostics should take an extra care to not segfault in such a scenario.1655if (!jitData)1656{1657return;1658}1659jitData->numberOfBuffers = numberOfBuffers;1660jitData->numberOfFrames = numberOfFrames;1661memset(jitData->pcList,0,(jitData->numberOfFrames)*(jitData->numberOfBuffers)*sizeof(U_8*));1662jitData->index=0;1663jitData->frameCount=0;1664}16651666return;1667}16681669static void accumulateAndPrintDebugCounters(J9JITConfig *jitConfig)1670{1671TR_Debug *debug = TR::Options::getDebug();1672if (debug)1673{1674TR::DebugCounterGroup *counters;1675counters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getStaticCounters();1676if (counters)1677{1678counters->accumulate();1679debug->printDebugCounters(counters, "Static debug counters");1680}1681counters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getDynamicCounters();1682if (counters)1683{1684counters->accumulate();1685debug->printDebugCounters(counters, "Dynamic debug counters");1686}1687}1688}16891690static void jitHookThreadStart(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1691{1692#if defined(TR_HOST_POWER)1693J9VMThread *vmThread = ((J9VMThreadStartedEvent *)eventData)->currentThread;16941695J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;1696TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);1697if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())1698{1699if (!IS_THREAD_RI_INITIALIZED(vmThread))1700{1701TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();1702hwProfiler->initializeThread(vmThread);1703}1704}1705#endif //defined(TR_HOST_POWER)1706}170717081709static void jitHookThreadCreate(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1710{1711J9VMThread *vmThread = ((J9VMThreadCreatedEvent *)eventData)->vmThread;1712initThreadAfterCreation(vmThread);1713}17141715static void jitHookThreadCrash(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1716{1717J9VMThread * vmThread = ((J9VMThreadCrashEvent *)eventData)->currentThread;1718J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;17191720if (jitConfig == 0)1721return; // if a hook gets called after freeJitConfig then not much else we can do17221723accumulateAndPrintDebugCounters(jitConfig);17241725fflush(stdout);17261727} // jitHookThreadCrash17281729static void jitHookThreadEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1730{1731J9VMThread * vmThread = ((J9VMThreadEndEvent *)eventData)->currentThread;1732J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;1733PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);17341735if (jitConfig == 0)1736return; // if a hook gets called after freeJitConfig then not much else we can do17371738if (TR::Options::getCmdLineOptions()->getOption(TR_CountWriteBarriersRT))1739{1740fprintf(stderr,"Thread %p: Executed %" OMR_PRIuPTR " barriers, %" OMR_PRIuPTR " went to slow path\n", vmThread, vmThread->debugEventData6, vmThread->debugEventData7);1741}1742return;1743}17441745static void jitHookThreadDestroy(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1746{1747J9VMThread * vmThread = ((J9VMThreadEndEvent *)eventData)->currentThread;1748J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;1749PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);17501751// Runtime Instrumentation1752TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);1753#if defined(ENABLE_GPU)1754extern void *terminateGPUThread(J9VMThread *vmThread);1755terminateGPUThread(vmThread);1756#endif1757TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();1758if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled() && hwProfiler->isHWProfilingAvailable(vmThread))1759{1760if (IS_THREAD_RI_INITIALIZED(vmThread))1761hwProfiler->deinitializeThread(vmThread);1762}17631764void *vmWithThreadInfo = vmThread->jitVMwithThreadInfo;17651766if (vmWithThreadInfo)1767{1768TR_J9VMBase *fej9 = (TR_J9VMBase *)vmWithThreadInfo;1769fej9->freeSharedCache();1770vmThread->jitVMwithThreadInfo = 0;1771j9mem_free_memory(vmWithThreadInfo);1772}17731774void *ExceptionHandlerCache = vmThread->jitExceptionHandlerCache;17751776if (ExceptionHandlerCache)1777{1778vmThread->jitExceptionHandlerCache = 0;1779j9mem_free_memory(ExceptionHandlerCache);1780}17811782void *ArtifactSearchCache = vmThread->jitArtifactSearchCache;1783if (ArtifactSearchCache)1784{1785vmThread->jitArtifactSearchCache=0;1786j9mem_free_memory(ArtifactSearchCache);1787}17881789J9JitPrivateThreadData * jitData = (J9JitPrivateThreadData *)vmThread->jitPrivateData;1790if(jitData && jitConfig)1791{1792vmThread->jitPrivateData=0;1793TR_Memory::jitPersistentFree(jitData);1794}179517961797#ifdef J9VM_INTERP_AOT_COMPILE_SUPPORT1798vmWithThreadInfo = vmThread->aotVMwithThreadInfo;1799if (vmWithThreadInfo)1800{1801TR_J9VMBase *vm = (TR_J9VMBase *)vmWithThreadInfo;1802vm->freeSharedCache();1803vmThread->aotVMwithThreadInfo = 0;1804j9mem_free_memory(vmWithThreadInfo);1805}1806#endif18071808return;1809}18101811#if defined(J9VM_OPT_CRIU_SUPPORT)1812static void jitHookPrepareCheckpoint(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1813{1814}18151816static void jitHookPrepareRestore(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1817{1818J9VMClassesUnloadEvent * restoreEvent = (J9VMClassesUnloadEvent *)eventData;1819J9VMThread * vmThread = restoreEvent->currentThread;1820J9JavaVM * javaVM = vmThread->javaVM;18211822/* If the restored run does not allow further checkpoints, then1823* remove the portability restrictions on the target CPU (used1824* for JIT compiles) to allow optimal code generation1825*/1826if (!javaVM->internalVMFunctions->isCheckpointAllowed(vmThread))1827{1828TR::Compiler->target.cpu = TR::CPU::detect(TR::Compiler->omrPortLib);1829jitConfig->targetProcessor = TR::Compiler->target.cpu.getProcessorDescription();1830}1831}1832#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */18331834#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)1835static void jitHookClassesUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1836{1837J9VMClassesUnloadEvent * unloadedEvent = (J9VMClassesUnloadEvent *)eventData;1838J9VMThread * vmThread = unloadedEvent->currentThread;1839J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;18401841TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);1842TR::PersistentInfo * persistentInfo = compInfo->getPersistentInfo();18431844// Here we need to set CompilationShouldBeInterrupted. Currently if the TR_EnableNoVMAccess is not1845// set the compilation is stopped, but should be notify not to continue afterwards.1846//1847compInfo->setAllCompilationsShouldBeInterrupted();18481849bool firstRange = true;1850bool coldRangeUninitialized = true;1851uintptr_t rangeStartPC = 0;1852uintptr_t rangeEndPC = 0;1853uintptr_t rangeColdStartPC = 0;1854uintptr_t rangeColdEndPC = 0;18551856uintptr_t rangeStartMD = 0;1857uintptr_t rangeEndMD = 0;18581859TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();18601861bool hasMethodOverrideAssumptions = false;1862bool hasClassExtendAssumptions = false;1863bool hasClassUnloadAssumptions = false;1864bool hasClassRedefinitionAssumptions = false;1865bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassUnloading);1866if (p)1867{1868TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "Classes unloaded \n");1869}18701871//All work here is only done if there is a chtable. Small have no table, thus nothing to do.18721873TR_PersistentCHTable * table = 0;1874if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))1875table = persistentInfo->getPersistentCHTable();18761877if (table && table->isActive())1878{1879TR_FrontEnd * fe = TR_J9VMBase::get(jitConfig, vmThread);18801881// If space for the array of visited superclasses has not yet been allocated, do it now1882// There is no race condition because everything is frozen during class unloading1883if (!persistentInfo->getVisitedSuperClasses())1884persistentInfo->setVisitedSuperClasses((TR_OpaqueClassBlock **)TR_Memory::jitPersistentAlloc(MAX_SUPERCLASSES*sizeof(TR_OpaqueClassBlock *), TR_Memory::PersistentInfo));1885// The following is safe to execute even if there is no backing for the visitedSuperClasses array1886persistentInfo->clearVisitedSuperClasses();18871888PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);1889J9ClassWalkState classWalkState;1890J9Class * j9clazz;1891TR_OpaqueClassBlock *clazz;1892j9clazz = vmThread->javaVM->internalVMFunctions->allClassesStartDo(&classWalkState, vmThread->javaVM, NULL);1893while (j9clazz)1894{1895// If the romableAotITable field is set to 0, that means this class was not caught1896// by the JIT load hook and has not been loaded.1897//1898if (J9CLASS_FLAGS(j9clazz) & J9AccClassDying && j9clazz->romableAotITable !=0 )1899{1900clazz = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(j9clazz);1901table->classGotUnloadedPost(fe,clazz); // side-effect: builds the array of visited superclasses1902}1903j9clazz = vmThread->javaVM->internalVMFunctions->allClassesNextDo(&classWalkState);1904}19051906vmThread->javaVM->internalVMFunctions->allClassesEndDo(&classWalkState);190719081909TR_OpaqueClassBlock **visitedSuperClasses = persistentInfo->getVisitedSuperClasses();1910if (visitedSuperClasses && !persistentInfo->tooManySuperClasses())1911{1912int32_t numSuperClasses = persistentInfo->getNumVisitedSuperClasses();19131914for (int32_t index = 0; index < numSuperClasses; index++)1915{1916clazz = visitedSuperClasses[index];1917TR_PersistentClassInfo *classInfo = table->findClassInfo(clazz);1918if (classInfo)1919classInfo->resetVisited();1920}1921}1922else1923{1924table->resetVisitedClasses();1925}1926}19271928return;1929}19301931/// Side effect1932/// 1. Every anon class to be unloaded will have j9clazz->classLoader = NULL1933/// 2. Every j9clazz->jitMetaDataList will be set to NULL1934static void jitHookAnonClassesUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)1935{1936J9VMAnonymousClassesUnloadEvent * unloadedEvent = (J9VMAnonymousClassesUnloadEvent *)eventData;1937J9VMThread * vmThread = unloadedEvent->currentThread;1938UDATA anonymousClassUnloadCount = unloadedEvent->anonymousClassUnloadCount;19391940if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseClassUnloading))1941TR_VerboseLog::writeLineLocked(TR_Vlog_GC, "jitHookAnonClassesUnload: unloading %u anonymous classes\n", (uint32_t)anonymousClassUnloadCount);19421943// Create a dummy classLoader and change j9class->classLoader to point to this fake one1944J9ClassLoader dummyClassLoader;1945int32_t numClasses = 0;1946bool needsMCCCleaning = false;1947for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink)1948{1949numClasses++;1950j9clazz->classLoader = &dummyClassLoader;19511952if (j9clazz->classFlags & J9ClassContainsMethodsPresentInMCCHash)1953{1954needsMCCCleaning = true;1955}1956}1957// TODO assert that numClasses == anonymousClassUnloadCount19581959// Concatenate all the lists of metadata from each class to be unloaded into1960// a bigger list (fullChainOfMetaData). Then attach this bigger list to the dummy classloader1961//1962J9JITExceptionTable* fullChainOfMetaData = NULL;1963uint32_t numMetaData = 0;1964for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink)1965{1966if (j9clazz->jitMetaDataList) // is there any metadata for this class?1967{1968// ASSUME that j9clazz->extendedClassFlags & J9ClassContainsJittedMethods is non zero1969// Find the end the metadata list1970J9JITExceptionTable *lastMetaData = j9clazz->jitMetaDataList;1971for (; lastMetaData->nextMethod; lastMetaData = lastMetaData->nextMethod)1972numMetaData++;1973// Attach the chain assembled so far at the end of the current list1974lastMetaData->nextMethod = fullChainOfMetaData;1975if (fullChainOfMetaData)1976fullChainOfMetaData->prevMethod = lastMetaData;1977fullChainOfMetaData = j9clazz->jitMetaDataList;1978j9clazz->jitMetaDataList = NULL; // don't want metadata appearing in two lists1979}1980}1981// If I have any metadata to be cleaned up1982if (fullChainOfMetaData)1983{1984if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseClassUnloading))1985TR_VerboseLog::writeLineLocked(TR_Vlog_GC, "jitHookAnonClassesUnload: will remove %u metadata entities\n", numMetaData);1986// Attach the full chain to the dummy classloader1987dummyClassLoader.jitMetaDataList = fullChainOfMetaData;1988// Perform the cleanup1989jitRemoveAllMetaDataForClassLoader(vmThread, &dummyClassLoader);1990}19911992// Remove entries from the MCC hash tables related to trampolines1993if (needsMCCCleaning)1994{1995if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseClassUnloading))1996TR_VerboseLog::writeLineLocked(TR_Vlog_GC, "jitHookAnonClassesUnload: will perform MCC cleaning\n");1997TR::CodeCacheManager::instance()->onClassUnloading(&dummyClassLoader);1998}19992000J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;2001TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);2002#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)2003compInfo->cleanDLTRecordOnUnload();2004if (compInfo->getDLT_HT())2005compInfo->getDLT_HT()->onClassUnloading();2006#endif20072008compInfo->getLowPriorityCompQueue().purgeEntriesOnClassLoaderUnloading(&dummyClassLoader);20092010compInfo->getPersistentInfo()->incGlobalClassUnloadID();2011#if defined(J9VM_INTERP_PROFILING_BYTECODES)2012if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))2013{2014TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, vmThread));2015TR_IProfiler *iProfiler = vmj9->getIProfiler();2016if (iProfiler) // even if Iprofiler is disabled, there might be some buffers in the queue2017{ // which need to be invalidated2018iProfiler->invalidateProfilingBuffers();2019}2020}2021#endif20222023// Invalidate the buffers from the hardware profiler2024if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())2025compInfo->getHWProfiler()->invalidateProfilingBuffers();20262027// Don't want j9classes to point to the dummy class loader that will disappear2028for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink)2029{2030cgOnClassUnloading(j9clazz);2031j9clazz->classLoader = NULL;2032}2033}2034#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/203520362037#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)2038static void jitHookClassUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)2039{2040J9VMClassUnloadEvent * unloadedEvent = (J9VMClassUnloadEvent *)eventData;2041J9VMThread * vmThread = unloadedEvent->currentThread;2042J9Class * j9clazz = unloadedEvent->clazz;2043J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;20442045TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);20462047TR_J9VMBase * fej9 = TR_J9VMBase::get(jitConfig, vmThread);2048TR_OpaqueClassBlock *clazz = fej9->convertClassPtrToClassOffset(j9clazz);20492050{2051TR::ClassTableCriticalSection removeClasses(fej9);2052TR_ASSERT(!removeClasses.acquiredVMAccess(), "jitHookClassUnload should already have VM access");2053TR_LinkHead0<TR_ClassHolder> *classList = compInfo->getListOfClassesToCompile();20542055TR_ClassHolder *prevClass = NULL;2056TR_ClassHolder *crtClass = classList->getFirst();2057while (crtClass)2058{2059if (crtClass->getClass() == j9clazz) // found the class; remove it from the list2060{2061classList->removeAfter(prevClass, crtClass);2062//break; // we cannot have duplicates - we might have duplicates, see JTC-JAT 67575 comment 1042063}2064prevClass = crtClass;2065crtClass = crtClass->getNext();2066}2067}20682069bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassUnloading);2070if (p)2071{2072TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "Class unloading for class=0x%p\n", j9clazz);2073}20742075PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);20762077// remove from compilation request queue any methods that belong to this class2078fej9->acquireCompilationLock();2079fej9->invalidateCompilationRequestsForUnloadedMethods(clazz, false);2080fej9->releaseCompilationLock();20812082J9Method * resolvedMethods = (J9Method *) fej9->getMethods((TR_OpaqueClassBlock*)j9clazz);2083uint32_t numMethods = fej9->getNumMethods((TR_OpaqueClassBlock*)j9clazz);2084uintptr_t methodsStartAddr = 0;2085uintptr_t methodsEndAddr = 0;20862087if ( numMethods >0 )2088{2089methodsStartAddr = TR::Compiler->mtd.bytecodeStart( (TR_OpaqueMethodBlock *)&(resolvedMethods[0]));2090methodsEndAddr = TR::Compiler->mtd.bytecodeStart( (TR_OpaqueMethodBlock *)&(resolvedMethods[numMethods-1]))2091+ TR::Compiler->mtd.bytecodeSize( (TR_OpaqueMethodBlock *)&(resolvedMethods[numMethods-1]) );2092}20932094static char *disableUnloadedClassRanges = feGetEnv("TR_disableUnloadedClassRanges");2095if (!disableUnloadedClassRanges)2096compInfo->getPersistentInfo()->addUnloadedClass(clazz, methodsStartAddr, (uint32_t)(methodsEndAddr-methodsStartAddr));20972098TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();2099rat->notifyClassUnloadEvent(fej9, 0, clazz, clazz);21002101// Patch all the sites registered with dummy class pointer (-1)2102// These sites are patched each time any class is loaded2103//2104// These will be IPIC slots registered at compile time (PICs have not been populated yet)2105//2106rat->notifyClassUnloadEvent(fej9, 0, (TR_OpaqueClassBlock *)-1, clazz);21072108// THIS ONLY NEEDS TO BE DONE FOR s390-312109// BEGIN21102111{2112TR::VMAccessCriticalSection notifyClassUnloadEvent(fej9);2113for (J9ITable * iTableEntry = (J9ITable *) TR::Compiler->cls.convertClassOffsetToClassPtr(clazz)->iTable; iTableEntry; iTableEntry = iTableEntry->next)2114{2115TR_OpaqueClassBlock *interfaceCl = fej9->convertClassPtrToClassOffset(iTableEntry->interfaceClass);2116rat->notifyClassUnloadEvent(fej9, 0, interfaceCl, clazz);2117}2118}21192120// END21212122TR_PersistentCHTable * table = 0;2123if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))2124table = compInfo->getPersistentInfo()->getPersistentCHTable();2125if (table && table->isActive())2126table->classGotUnloaded(fej9, clazz);21272128#if defined(J9VM_OPT_JITSERVER)2129// Add to JITServer unload list2130if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)2131{2132compInfo->getUnloadedClassesTempList()->push_back(clazz);2133// Loop through the set to find the class that needs to be purged.2134// Once found erase from the set.2135compInfo->getclassesCachedAtServer().erase(unloadedEvent->clazz);2136if (auto deserializer = compInfo->getJITServerAOTDeserializer())2137deserializer->invalidateClass(vmThread, j9clazz);2138}2139#endif2140}2141#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/21422143#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)2144static void jitHookClassLoaderUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)2145{2146J9VMClassLoaderUnloadEvent * unloadedEvent = (J9VMClassLoaderUnloadEvent *)eventData;2147J9VMThread * vmThread = unloadedEvent->currentThread;2148J9ClassLoader * classLoader = unloadedEvent->classLoader;21492150// Assumptions are registered during class loading event. For a class loader that has never loaded a class, the JIT won't know about it2151if (classLoader->classSegments == NULL)2152return;21532154J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;21552156TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);21572158bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassUnloading);2159if (p)2160{2161TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "Class unloading for classLoader=0x%p\n", classLoader);2162}2163compInfo->getPersistentInfo()->incGlobalClassUnloadID();21642165PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);21662167if (classLoader->flags & J9CLASSLOADER_CONTAINS_JITTED_METHODS)2168jitRemoveAllMetaDataForClassLoader(vmThread, classLoader);21692170if (classLoader->flags & J9CLASSLOADER_CONTAINS_METHODS_PRESENT_IN_MCC_HASH)2171TR::CodeCacheManager::instance()->onClassUnloading(classLoader);21722173// CodeGen-specific actions on class unloading2174cgOnClassUnloading(classLoader);21752176compInfo->getLowPriorityCompQueue().purgeEntriesOnClassLoaderUnloading(classLoader);21772178#if defined(J9VM_INTERP_PROFILING_BYTECODES)2179if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))2180{2181TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, vmThread));2182TR_IProfiler *iProfiler = vmj9->getIProfiler();2183if (iProfiler) // even if Iprofiler is disabled, there might be some buffers in the queue2184{ // which need to be invalidated2185iProfiler->invalidateProfilingBuffers();2186}2187}2188#endif21892190// Invalidate the buffers from the hardware profiler2191if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())2192compInfo->getHWProfiler()->invalidateProfilingBuffers();21932194compInfo->getPersistentInfo()->getPersistentClassLoaderTable()->removeClassLoader(vmThread, classLoader);21952196#if defined(J9VM_OPT_JITSERVER)2197if (auto deserializer = compInfo->getJITServerAOTDeserializer())2198deserializer->invalidateClassLoader(vmThread, classLoader);2199#endif /* defined(J9VM_OPT_JITSERVER) */2200}22012202#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/22032204#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) && defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)2205static void jitHookClassLoadersUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)2206{2207J9VMClassUnloadEvent * unloadedEvent = (J9VMClassUnloadEvent *)eventData;2208J9VMThread * vmThread = unloadedEvent->currentThread;2209J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;2210TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);2211compInfo->cleanDLTRecordOnUnload();2212if (compInfo->getDLT_HT())2213compInfo->getDLT_HT()->onClassUnloading();2214}2215#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING) and defined (J9VM_JIT_DYNAMIC_LOOP_TRANSFER) */22162217void jitDiscardPendingCompilationsOfNatives(J9VMThread *vmThread, J9Class *clazz)2218{2219J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;2220TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);2221// need to get the compilation lock before updating the queue2222compInfo->acquireCompilationLock();2223compInfo->setAllCompilationsShouldBeInterrupted();2224compInfo->invalidateRequestsForNativeMethods(clazz, vmThread);2225compInfo->releaseCompilationLock();2226}22272228static bool classesAreRedefinedInPlace()2229{2230if(TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR))2231return true;2232else return false;2233}22342235static bool methodsAreRedefinedInPlace()2236{2237// NOTE: making this return "true" will require careful thought.2238// Don't expect callers to respond properly. At the time this comment was2239// written, we had never tested that configuration. Consider calls to this2240// function just to be markers for places in the code that may require attention.2241//2242return false;2243}22442245// Hack markers2246#define VM_PASSES_SAME_CLASS_TWICE 122472248#if (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))2249void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRedefinedClass *classList, UDATA extensionsUsed)2250{2251reportHook(currentThread, "jitClassesRedefined");22522253if ((classCount == 0 || classList == NULL) && TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR))2254{2255reportHookFinished(currentThread, "jitClassesRedefined", "Nothing to do");2256return;2257}22582259J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;2260TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);2261TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);2262TR_PersistentCHTable * table = 0;2263if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))2264table = compInfo->getPersistentInfo()->getPersistentCHTable();22652266TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();22672268TR_OpaqueClassBlock *oldClass, *newClass;2269J9Method *oldMethod, *newMethod;22702271// A few definitions. In the jit's terminology:2272// The "stale method" is the one that points at the old bytecodes from before the hot swap.2273// The "stale class" is the one that points at the stale methods.2274// The "old class" is the j9class struct that existed before the hot swap.2275// The "new class" is the one created in response to the hot swap.2276//2277// NOTE: THIS MAY NOT MATCH THE VM'S TERMINOLOGY!2278//2279// Here we define various aliases so we can freely use the terminology we want.2280//2281TR_OpaqueClassBlock *&freshClass = classesAreRedefinedInPlace()? oldClass : newClass;2282TR_OpaqueClassBlock *&staleClass = classesAreRedefinedInPlace()? newClass : oldClass;2283J9Method *&freshMethod = methodsAreRedefinedInPlace()? oldMethod : newMethod;2284J9Method *&staleMethod = methodsAreRedefinedInPlace()? newMethod : oldMethod;22852286int methodCount;2287J9JITMethodEquivalence *methodList;2288bool equivalent;2289void* startPC;2290int i, j;22912292// JIT compilation thread could be running without exclusive access so we need to explicitly stop it2293if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))2294{2295TR::MonitorTable::get()->getClassUnloadMonitor()->enter_write();2296}22972298// need to get the compilation lock before updating the queue2299fe->acquireCompilationLock();2300compInfo->setAllCompilationsShouldBeInterrupted();2301J9JITRedefinedClass *classPair = classList;2302if (!TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug))2303{2304for (i = 0; i < classCount; i++)2305{2306freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->newClass);2307if (VM_PASSES_SAME_CLASS_TWICE)2308staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(((J9Class*)freshClass)->replacedClass);2309else2310staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->oldClass);2311methodCount = classPair->methodCount;2312methodList = classPair->methodList;23132314int32_t length;2315char *name = fe->getClassNameChars((TR_OpaqueClassBlock*)freshClass, length);2316reportHookDetail(currentThread, "jitClassesRedefined", "Redefined class old=%p new=%p stale=%p fresh=%p %.*s", oldClass, newClass, staleClass, freshClass, length, name);23172318compInfo->getLowPriorityCompQueue().purgeEntriesOnClassRedefinition((J9Class*)staleClass);23192320// Step 1 remove from compilation request queue any methods that are redefined2321reportHookDetail(currentThread, "jitClassesRedefined", " Invalidate compilation requests for classes old=%p and new=%p", oldClass, newClass);2322fe->invalidateCompilationRequestsForUnloadedMethods(oldClass, true);2323fe->invalidateCompilationRequestsForUnloadedMethods(newClass, true);23242325for (j = 0; j < methodCount; j++)2326{2327staleMethod = methodList[j].oldMethod;2328freshMethod = methodList[j].newMethod;2329equivalent = (bool) methodList[j].equivalent;23302331reportHookDetail(currentThread, "jitClassesRedefined", " Notify MCC for method stale=%p fresh=%p e=%d", staleMethod, freshMethod, equivalent);2332TR::CodeCacheManager::instance()->onClassRedefinition(reinterpret_cast<TR_OpaqueMethodBlock *>(staleMethod),2333reinterpret_cast<TR_OpaqueMethodBlock *>(freshMethod));2334// Step 2 invalidate methods that are already compiled and trigger a new compilation.2335if (staleMethod && freshMethod && (startPC = compInfo->getPCIfCompiled(staleMethod)))2336{2337// Update the ram method information in PersistentMethodInfo2338TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(startPC);2339if (bodyInfo)2340{2341reportHookDetail(currentThread, "jitClassesRedefined", " Invalidate method body stale=%p startPC=%p", staleMethod, startPC);2342TR::Recompilation::invalidateMethodBody(startPC, fe);2343bodyInfo->setDisableSampling(true);2344TR_PersistentMethodInfo *pmi = bodyInfo->getMethodInfo();2345if (pmi)2346{2347pmi->setHasBeenReplaced();2348}2349// Note: we don't do pmi->setMethodInfo here because (a) they'll be patched by runtime2350// assumptions anyway, and (b) we can only get our hands on the latest PMI, not all the2351// older ones.2352}2353// Same as TR_ResolvedMethod::isNative without allocating Scratch Memory2354else if(_J9ROMMETHOD_J9MODIFIER_IS_SET((J9_ROM_METHOD_FROM_RAM_METHOD(staleMethod)), J9AccNative ))2355{2356reportHookDetail(currentThread, "jitClassesRedefined", "No need to invalidate native method stale=%p startPC=%p", staleMethod, startPC);2357}2358else2359{2360reportHookDetail(currentThread, "jitClassesRedefined", "WARNING! Cannot invalidate method body stale=%p startPC=%p", staleMethod, startPC);2361TR_ASSERT(0,"JIT HCR should make all methods recompilable, so startPC=%p should have a persistentBodyInfo", startPC);2362}2363}2364}2365classPair = (J9JITRedefinedClass *) ((char *) classPair->methodList + (classPair->methodCount * sizeof(struct J9JITMethodEquivalence)));2366}2367}2368//for extended HCR under FSD, all the methods in code cache needs to be2369//discarded because of inlining2370else2371{2372// Don't know what got replaced, so get pessimistic and clear the whole compilation queue2373reportHookDetail(currentThread, "jitClassesRedefined", " Invalidate all compilation requests");2374fe->invalidateCompilationRequestsForUnloadedMethods(NULL, true);23752376//clean up the trampolines2377TR::CodeCacheManager::instance()->onFSDDecompile();2378}23792380fe->releaseCompilationLock();23812382classPair = classList;2383for (i = 0; i < classCount; i++)2384{2385#if defined(J9VM_OPT_JITSERVER)2386// Add to JITServer unload list2387if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)2388{2389compInfo->getUnloadedClassesTempList()->push_back((TR_OpaqueClassBlock *) classPair->oldClass);2390if (auto deserializer = compInfo->getJITServerAOTDeserializer())2391deserializer->invalidateClass(currentThread, classPair->oldClass);2392}2393#endif2394freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->newClass);2395if (VM_PASSES_SAME_CLASS_TWICE)2396staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(((J9Class*)freshClass)->replacedClass);2397else2398staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->oldClass);2399methodCount = classPair->methodCount;2400methodList = classPair->methodList;24012402// Do this before modifying the CHTable2403if (table && table->isActive() && TR::Options::sharedClassCache() && TR::Options::getCmdLineOptions()->getOption(TR_EnableClassChainValidationCaching))2404{2405table->resetCachedCCVResult(fe, oldClass);2406}24072408// Step 3 patch modified classes2409if (rat)2410{2411reportHookDetail(currentThread, "jitClassesRedefined", " Notify RAT on class old=%p fresh=%p", oldClass, freshClass);2412rat->notifyClassRedefinitionEvent(fe, 0, oldClass, freshClass);2413}2414for (j = 0; j < methodCount; j++)2415{2416staleMethod = methodList[j].oldMethod;2417freshMethod = methodList[j].newMethod;2418bool isSMP = 1; // conservative2419if (table)2420{2421reportHookDetail(currentThread, "jitClassesRedefined", " Notify CHTable on method old=%p fresh=%p", oldMethod, freshMethod);2422table->methodGotOverridden(fe, compInfo->persistentMemory(), (TR_OpaqueMethodBlock*)freshMethod, (TR_OpaqueMethodBlock*)oldMethod, isSMP);2423}2424// Step 4 patch modified J9Method2425if (oldMethod && newMethod && rat)2426{2427reportHookDetail(currentThread, "jitClassesRedefined", " Notify RAT on method old=%p fresh=%p", oldMethod, freshMethod);2428rat->notifyClassRedefinitionEvent(fe, 0,2429oldMethod,2430freshMethod);24312432// Same as TR_ResolvedMethod::virtualMethodIsOverridden without allocating Scratch Memory2433if ((UDATA)oldMethod->constantPool & J9_STARTPC_METHOD_IS_OVERRIDDEN)2434{2435UDATA *cp = (UDATA*)&(newMethod->constantPool);2436*cp |= J9_STARTPC_METHOD_IS_OVERRIDDEN;2437}2438}2439}2440// Step 5 patch and update virtual guard. may also need to refresh CHTable2441if (table)2442{2443reportHookDetail(currentThread, "jitClassesRedefined", " Notify CHTable on class old=%p fresh=%p", oldClass, freshClass);2444table->classGotRedefined(fe, oldClass, freshClass);2445}24462447classPair = (J9JITRedefinedClass *) ((char *) classPair->methodList + (classPair->methodCount * sizeof(struct J9JITMethodEquivalence)));2448}24492450#if defined(J9VM_OPT_JITSERVER)2451if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && extensionsUsed)2452{2453compInfo->getUnloadedClassesTempList()->push_back(ClientSessionData::mustClearCachesFlag);2454}2455#endif24562457if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))2458{2459TR::MonitorTable::get()->getClassUnloadMonitor()->exit_write();2460}24612462// In extended HCR, empty classList means methods are being added or removed from classes2463// Fall back to TR_MimicInterpreterFrameShape in this case because it's not properly2464// handled from VM side2465if (classCount == 0 || classList == NULL)2466TR::Options::getCmdLineOptions()->setOption(TR_MimicInterpreterFrameShape);24672468reportHookFinished(currentThread, "jitClassesRedefined");2469}24702471void jitFlushCompilationQueue(J9VMThread * currentThread, J9JITFlushCompilationQueueReason reason)2472{2473char *buffer = "unknown reason";2474if (reason == J9FlushCompQueueDataBreakpoint)2475buffer = "DataBreakpoint";2476else2477TR_ASSERT(0, "unexpected use of jitFlushCompilationQueue");24782479reportHook(currentThread, "jitFlushCompilationQueue ", buffer);24802481J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;2482TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);2483TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);24842485// JIT compilation thread could be running without exclusive access so we need to explicitly stop it2486if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))2487{2488TR::MonitorTable::get()->getClassUnloadMonitor()->enter_write();2489}24902491// need to get the compilation lock before updating the queue2492fe->acquireCompilationLock();2493compInfo->setAllCompilationsShouldBeInterrupted();2494reportHookDetail(currentThread, "jitFlushCompilationQueue", " Invalidate all compilation requests");2495fe->invalidateCompilationRequestsForUnloadedMethods(NULL, true);2496//clean up the trampolines2497TR::CodeCacheManager::instance()->onFSDDecompile();2498fe->releaseCompilationLock();24992500if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))2501{2502TR::MonitorTable::get()->getClassUnloadMonitor()->exit_write();2503}25042505reportHookFinished(currentThread, "jitFlushCompilationQueue ", buffer);2506}25072508#endif // #if (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))25092510void jitMethodBreakpointed(J9VMThread *currentThread, J9Method *j9method)2511{2512J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;2513TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);2514TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);2515TR_RuntimeAssumptionTable *rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();25162517reportHook(currentThread, "jitMethodbreakpointed", "j9method %p\n", j9method);25182519if (rat)2520{2521rat->notifyMethodBreakpointed(fe, reinterpret_cast<TR_OpaqueMethodBlock *>(j9method));2522}25232524reportHookFinished(currentThread, "jitMethodbreakpointed");2525}25262527/*2528* JIT hook called by the VM on the event of illegal modification. Runtime assumption table will be notified.2529*/2530void jitIllegalFinalFieldModification(J9VMThread *currentThread, J9Class *fieldClass)2531{2532J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;2533TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);2534TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);25352536// Set the bit so that VM doesn't report the modification next time2537fieldClass->classFlags |= J9ClassHasIllegalFinalFieldModifications;25382539#if defined(J9VM_OPT_JITSERVER)2540if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)2541{2542// Don't execute this hook at the jitserver side2543return;2544}2545else if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)2546{2547TR_OpaqueClassBlock *clazz = fe->convertClassPtrToClassOffset(fieldClass);2548compInfo->getSequencingMonitor()->enter();2549compInfo->getIllegalFinalFieldModificationList()->push_back(clazz);2550compInfo->getSequencingMonitor()->exit();2551}2552#endif25532554int32_t length;2555char *className = fe->getClassNameChars((TR_OpaqueClassBlock*)fieldClass, length);2556reportHook(currentThread, "jitIllegalFinalFieldModification", "class %p %.*s", fieldClass, length, className);25572558TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();2559if (rat)2560{2561rat->notifyIllegalStaticFinalFieldModificationEvent(fe, fieldClass);2562}2563reportHookFinished(currentThread, "jitIllegalFinalFieldModification");2564}25652566#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)2567// JIT hook called by the VM to update the target of a MutableCallSite.2568void jitSetMutableCallSiteTarget(J9VMThread *vmThread, j9object_t mcs, j9object_t newTarget)2569{2570J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;2571TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);2572TR_J9VMBase *fej9 = TR_J9VMBase::get(jitConfig, vmThread);2573TR_RuntimeAssumptionTable *rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();25742575bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);2576bool details = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails);2577verbose = verbose || details;25782579TR_OpaqueClassBlock *mcsClass = fej9->getObjectClass((uintptr_t)mcs);2580uintptr_t targetOffset = fej9->getInstanceFieldOffset(2581mcsClass, "target", "Ljava/lang/invoke/MethodHandle;");25822583TR::ClassTableCriticalSection commit(fej9);25842585// There are no concurrent modifications because target is only modified2586// while holding the CH table lock.2587uintptr_t prevTarget = fej9->getReferenceFieldAt((uintptr_t)mcs, targetOffset);2588if ((uintptr_t)newTarget == prevTarget)2589return; // Nothing to do.25902591// The CH table lock must be acquired before reading the cookie. Otherwise,2592// a nonzero value written by another thread (in the compiler's CH table2593// commit phase) won't necessarily be observed; and worse, if this MCS2594// object were first inlined in a compilation that is committing2595// concurrently, the following would be possible even with strong memory2596// ordering:2597//2598// 1. jitSetMutableCallSiteTarget() reads the cookie, which is zero, so no2599// assumptions will be invalidated; then2600//2601// 2. the compilation reads the MCS target during CH table commit, which2602// matches what it saw during inlining, so it considers its assumption2603// valid; then2604//2605// 3. in any order, the compilation finishes and the MCS target is updated,2606// resulting in a compiled body that has inlined the wrong target.26072608uintptr_t cookie = fej9->mutableCallSiteCookie((uintptr_t)mcs);2609if (cookie == 0)2610{2611if (verbose)2612{2613TR_VerboseLog::writeLineLocked(2614TR_Vlog_HD, "%p skipping nonexistent cookie", vmThread);2615}2616}2617else2618{2619// There may be assumptions to invalidate. Any such assumptions must be2620// invalidated before updating the target field. Otherwise, another2621// thread concurrently running JIT-compiled code where the previous2622// target is inlined could read the new target object from the field and2623// still pass the MCS target guard into the inlined body, even though the2624// freshly loaded target differs from the known object used during2625// optimization.2626//2627// While it would actually be OK to continue using the old target until2628// syncAll() is called, code optimized based on known object information2629// does not keep using the original reference it had when it was2630// compiled. Instead, it retrieves the reference at runtime using the2631// original chain of loads. The compiler will have transformed some but2632// not necessarily all of the uses of this reference, so if a different2633// reference is found at runtime, inconsistencies will result.2634//2635// For example, suppose the compiled code gets the mutable call site MCS2636// and then updates ((Foo)((Species_L)MCS.target).argL0).f. Making use of2637// the known object information, the compiler has likely improved the2638// code so that it stores to MCS.target.argL0.f without any casts, but2639// (crucially) the object reference MCS.target.argL0 is not truly2640// constant-folded, so it must be found by chasing pointers at runtime.2641// If MCS.target is changed to e.g. an instance of Species_I, and if the2642// optimized code is still allowed to run, then the load of argL0 will2643// reinterpret the bound integer as a reference, and the subsequent store2644// will dereference it. Kaboom!26452646if (verbose)2647{2648TR_VerboseLog::writeLineLocked(2649TR_Vlog_HD, "%p notifying cookie %p", vmThread, (void*)cookie);2650}26512652rat->notifyMutableCallSiteChangeEvent(fej9, cookie);26532654if (verbose)2655{2656TR_VerboseLog::writeLineLocked(2657TR_Vlog_HD, "%p finished notifying cookie %p", vmThread, (void*)cookie);2658}2659}26602661// Finally, update the target. This must be done while the CH table lock is2662// still held. Otherwise, it would be possible for a concurrent compilation2663// to inline the wrong target without invalidating its guard:2664//2665// 1. jitSetMutableCallSiteTarget() invalidates MCS target guards for this2666// call site and releases the CH table lock; then2667//2668// 2. the compilation gets the CH table lock and starts its CH table commit,2669// wherein it observes the previous target, which matches what it saw2670// during inlining, so it considers its assumption valid; then2671//2672// 3. finally, the target is updated.2673//2674// Note that it's fine to use a regular (non-volatile) store here. For other2675// threads loading the target at runtime / in the interpreter, they are not2676// required to see the update before syncAll() is called. For compilations2677// in other threads, any subsequent CH table commit is guaranteed to see the2678// update due to synchronization via the CH table lock.26792680targetOffset += TR::Compiler->om.objectHeaderSizeInBytes();2681vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreObject(2682vmThread, mcs, targetOffset, newTarget, 0);2683}2684#endif26852686#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)2687static void jitHookInterruptCompilation(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)2688{2689MM_InterruptCompilationEvent * interruptCompilationEvent = (MM_InterruptCompilationEvent *)eventData;2690J9VMThread * vmThread = interruptCompilationEvent->currentThread;2691J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;2692TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);26932694//compInfo->setAllCompilationsShouldBeInterrupted();2695compInfo->getPersistentInfo()->setGCwillBlockOnClassUnloadMonitor();2696}2697#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/26982699// jitUpdateMethodOverride is called indirectly from updateCHTable2700//2701void jitUpdateMethodOverride(J9VMThread * vmThread, J9Class * cl, J9Method * overriddenMethod, J9Method * overriddingMethod)2702{2703J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;27042705TR_FrontEnd * vm = TR_J9VMBase::get(jitConfig, vmThread);27062707PORT_ACCESS_FROM_PORT(jitConfig->javaVM->portLibrary);27082709TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);27102711// Pretend that we are always running smp; current implementation2712// of virtual guard patching (on ia32/ppc) ignore it. Since patching2713// is infrequent anyway probably it is not worth maintaining two versions2714// of code for patching.2715// On Linux, get_number_CPUs calls sysconfig which has to generate and2716// parse /proc/stat (slow) -- if re-enabling, cache the isSMP flag2717// rather than querying each time.2718//2719bool isSMP = 1; // conservative2720if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))2721{2722jitAcquireClassTableMutex(vmThread);2723compInfo->getPersistentInfo()->getPersistentCHTable()->methodGotOverridden(2724vm, compInfo->persistentMemory(), (TR_OpaqueMethodBlock *) overriddingMethod, (TR_OpaqueMethodBlock *) overriddenMethod, isSMP);2725jitReleaseClassTableMutex(vmThread);2726}2727}27282729/* updateOverriddenFlag() replaces jitUpdateInlineAttribute. See Design 1812 */27302731static void updateOverriddenFlag( J9VMThread *vm , J9Class *cl)2732{27332734static const char *traceIt = 0; // feGetEnv("TR_TraceUpdateOverridenFlag"); //this trace should only be enabled if it is needed27352736J9ROMClass *ROMCl = cl->romClass;27372738if(ROMCl->modifiers & J9AccInterface ) //Do nothing if interface2739return;27402741int32_t classDepth = J9CLASS_DEPTH(cl) - 1;27422743if (classDepth >= 0) // Do nothing if we don't have a superclass2744{2745J9Class * superCl = cl->superclasses[classDepth];27462747J9VTableHeader * superVTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(superCl);2748intptr_t methodCount = (intptr_t)superVTableHeader->size;2749J9Method ** superVTable = J9VTABLE_FROM_HEADER(superVTableHeader);2750J9Method ** subVTable = J9VTABLE_FROM_RAM_CLASS(cl);27512752intptr_t methodIndex=0;27532754while(methodCount--)2755{2756J9Method * superMethod = *superVTable++;2757J9Method * subMethod = *subVTable++;27582759J9ROMMethod *subROM = J9_ROM_METHOD_FROM_RAM_METHOD(subMethod);2760J9ROMMethod *superROM = J9_ROM_METHOD_FROM_RAM_METHOD(superMethod);27612762bool methodModifiersAreSafe = (subROM->modifiers & J9AccForwarderMethod) && !((subROM->modifiers & J9AccSynchronized) || (subROM->modifiers & J9AccStrict) || (subROM->modifiers & J9AccNative)) ;27632764if (traceIt)2765{2766char *classNameChars = (char *)J9UTF8_DATA(J9ROMCLASS_CLASSNAME(ROMCl));2767int32_t classNameLen = (int32_t)J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(ROMCl));2768char *superSignature = (char*)J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));2769int32_t superSigLen = (int32_t)J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));2770char *superName = (char*)J9UTF8_DATA(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));2771int32_t superNameLen = (int32_t) J9UTF8_LENGTH(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));2772char *subSignature = (char*)J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));2773int32_t subSigLen = (int32_t)J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));2774char *subName = (char*)J9UTF8_DATA(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));2775int32_t subNameLen = (int32_t)J9UTF8_LENGTH(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));27762777printf("class = %.*s superSignature = %.*s, superName = %.*s, supermodifers = %x , subSignature = %.*s, subName = %.*s, submodifiers = %x subMethod = %p methodModifiersAreSafe = %d\n"2778,classNameLen,classNameChars,superSigLen,superSignature,superNameLen,superName,(int)superROM->modifiers,subSigLen,subSignature,subNameLen,subName,(int)subROM->modifiers,subMethod,methodModifiersAreSafe );2779printf("For subROM %p:\n",subROM);27802781if(subROM->modifiers & J9AccAbstract) printf("\tsubMethod is J9AccAbstract (%x)\n",J9AccAbstract);2782if(subROM->modifiers & J9AccAnnotation) printf("\tsubMethod is J9AccAnnotation\n");2783if(subROM->modifiers & J9AccBridge) printf("\tsubMethod is J9AccBridge\n");2784if(subROM->modifiers & J9AccEmptyMethod) printf("\tsubMethod is J9AccEmptyMethod\n");2785if(subROM->modifiers & J9AccEnum) printf("\tsubMethod is J9AccEnum\n");2786if(subROM->modifiers & J9AccFinal) printf("\tsubMethod is J9AccFinal\n");2787if(subROM->modifiers & J9AccForwarderMethod) printf("\tsubMethod is J9AccForwarderMethod\n");2788if(subROM->modifiers & J9AccGetterMethod) printf("\tsubMethod is J9AccGetterMethod\n");2789if(subROM->modifiers & J9AccInterface) printf("\tsubMethod is J9AccInterface\n");2790if(subROM->modifiers & J9AccMethodCallerSensitive) printf("\tsubMethod is J9AccMethodCallerSensitive\n");2791if(subROM->modifiers & J9AccMethodFrameIteratorSkip) printf("\tsubMethod is J9AccMethodFrameIteratorSkip\n");2792if(subROM->modifiers & J9AccMethodHasBackwardBranches) printf("\tsubMethod is J9AccMethodHasBackwardBranches\n");2793if(subROM->modifiers & J9AccMethodHasDebugInfo) printf("\tsubMethod is J9AccMethodHasDebugInfo\n");2794if(subROM->modifiers & J9AccMethodHasDefaultAnnotation) printf("\tsubMethod is J9AccMethodHasDefaultAnnotation\n");2795if(subROM->modifiers & J9AccMethodHasExceptionInfo) printf("\tsubMethod is J9AccMethodHasExceptionInfo\n");2796if(subROM->modifiers & J9AccMethodHasGenericSignature) printf("\tsubMethod is J9AccMethodHasGenericSignature\n");2797if(subROM->modifiers & J9AccMethodHasMethodAnnotations) printf("\tsubMethod is J9AccMethodHasMethodAnnotations\n");2798if(subROM->modifiers & J9AccMethodHasParameterAnnotations) printf("\tsubMethod is J9AccMethodHasParameterAnnotations\n");2799if(subROM->modifiers & J9AccMethodHasStackMap) printf("\tsubMethod is J9AccMethodHasStackMap\n");2800if(subROM->modifiers & J9AccMethodObjectConstructor) printf("\tsubMethod is J9AccMethodObjectConstructor\n");2801if(subROM->modifiers & J9AccMethodReturn0) printf("\tsubMethod is J9AccMethodReturn0\n");2802if(subROM->modifiers & J9AccMethodReturn1) printf("\tsubMethod is J9AccMethodReturn1\n");2803if(subROM->modifiers & J9AccMethodReturn2) printf("\tsubMethod is J9AccMethodReturn2\n");2804if(subROM->modifiers & J9AccMethodReturnA) printf("\tsubMethod is J9AccMethodReturnA\n");2805if(subROM->modifiers & J9AccMethodReturnD) printf("\tsubMethod is J9AccMethodReturnD\n");2806if(subROM->modifiers & J9AccMethodReturnF) printf("\tsubMethod is J9AccMethodReturnF\n");2807if(subROM->modifiers & J9AccMethodReturnMask) printf("\tsubMethod is J9AccMethodReturnMask\n");2808if(subROM->modifiers & J9AccMethodReturnShift) printf("\tsubMethod is J9AccMethodReturnShift\n");2809if(subROM->modifiers & J9AccMethodVTable) printf("\tsubMethod is J9AccMethodVTable\n");2810if(subROM->modifiers & J9AccNative) printf("\tsubMethod is J9AccNative\n");2811if(subROM->modifiers & J9AccPrivate) printf("\tsubMethod is J9AccPrivate\n");2812if(subROM->modifiers & J9AccProtected) printf("\tsubMethod is J9AccProtected\n");2813if(subROM->modifiers & J9AccPublic) printf("\tsubMethod is J9AccPublic\n");2814if(subROM->modifiers & J9AccStatic) printf("\tsubMethod is J9AccStatic\n");2815if(subROM->modifiers & J9AccStrict) printf("\tsubMethod is J9AccStrict\n");2816if(subROM->modifiers & J9AccSuper) printf("\tsubMethod is J9AccSuper\n");2817if(subROM->modifiers & J9AccSynchronized) printf("\tsubMethod is J9AccSynchronized\n");2818if(subROM->modifiers & J9AccSynthetic) printf("\tsubMethod is J9AccSynthetic\n");2819if(subROM->modifiers & J9AccTransient) printf("\tsubMethod is J9AccTransient\n");2820if(subROM->modifiers & J9AccVarArgs) printf("\tsubMethod is J9AccVarArgs\n");2821if(subROM->modifiers & J9AccVolatile) printf("\tsubMethod is J9AccVolatile\n");28222823printf("For superROM %p:\n",superROM);28242825if(superROM->modifiers & J9AccAbstract) printf("\tsuperMethod is J9AccAbstract\n");2826if(superROM->modifiers & J9AccAnnotation) printf("\tsuperMethod is J9AccAnnotationt\n");2827if(superROM->modifiers & J9AccBridge) printf("\tsuperMethod is J9AccBridge\n");2828if(superROM->modifiers & J9AccEmptyMethod) printf("\tsuperMethod is J9AccEmptyMethod\n");2829if(superROM->modifiers & J9AccEnum) printf("\tsuperMethod is J9AccEnum\n");2830if(superROM->modifiers & J9AccFinal) printf("\tsuperMethod is J9AccFinal\n");2831if(superROM->modifiers & J9AccForwarderMethod) printf("\tsuperMethod is J9AccForwarderMethod\n");2832if(superROM->modifiers & J9AccGetterMethod) printf("\tsuperMethod is J9AccGetterMethod\n");2833if(superROM->modifiers & J9AccInterface) printf("\tsuperMethod is J9AccInterface\n");2834if(superROM->modifiers & J9AccMethodCallerSensitive) printf("\tsuperMethod is J9AccMethodCallerSensitive\n");2835if(superROM->modifiers & J9AccMethodFrameIteratorSkip) printf("\tsuperMethod is J9AccMethodFrameIteratorSkip\n");2836if(superROM->modifiers & J9AccMethodHasBackwardBranches) printf("\tsuperMethod is J9AccMethodHasBackwardBranches\n");2837if(superROM->modifiers & J9AccMethodHasDebugInfo) printf("\tsuperMethod is J9AccMethodHasDebugInfo\n");2838if(superROM->modifiers & J9AccMethodHasDefaultAnnotation) printf("\tsuperMethod is J9AccMethodHasDefaultAnnotation\n");2839if(superROM->modifiers & J9AccMethodHasExceptionInfo) printf("\tsuperMethod is J9AccMethodHasExceptionInfo\n");2840if(superROM->modifiers & J9AccMethodHasGenericSignature) printf("\tsuperMethod is J9AccMethodHasGenericSignature\n");2841if(superROM->modifiers & J9AccMethodHasMethodAnnotations) printf("\tsuperMethod is J9AccMethodHasMethodAnnotations\n");2842if(superROM->modifiers &J9AccMethodHasParameterAnnotations) printf("\tsuperMethod is J9AccMethodHasParameterAnnotations\n");2843if(superROM->modifiers & J9AccMethodHasStackMap) printf("\tsuperMethod is J9AccMethodHasStackMap\n");2844if(superROM->modifiers & J9AccMethodObjectConstructor) printf("\tsuperMethod is J9AccMethodObjectConstructor\n");2845if(superROM->modifiers & J9AccMethodReturn0) printf("\tsuperMethod is J9AccMethodReturn0\n");2846if(superROM->modifiers & J9AccMethodReturn1) printf("\tsuperMethod is J9AccMethodReturn1\n");2847if(superROM->modifiers & J9AccMethodReturn2) printf("\tsuperMethod is J9AccMethodReturn2\n");2848if(superROM->modifiers & J9AccMethodReturnA) printf("\tsuperMethod is J9AccMethodReturnA\n");2849if(superROM->modifiers & J9AccMethodReturnD) printf("\tsuperMethod is J9AccMethodReturnD\n");2850if(superROM->modifiers & J9AccMethodReturnF) printf("\tsuperMethod is J9AccMethodReturnF\n");2851if(superROM->modifiers & J9AccMethodReturnMask) printf("\tsuperMethod is J9AccMethodReturnMask\n");2852if(superROM->modifiers & J9AccMethodReturnShift) printf("\tsuperMethod is J9AccMethodReturnShift\n");2853if(superROM->modifiers & J9AccMethodVTable) printf("\tsuperMethod is J9AccMethodVTable\n");2854if(superROM->modifiers & J9AccNative) printf("\tsuperMethod is J9AccNative\n");2855if(superROM->modifiers & J9AccPrivate) printf("\tsuperMethod is J9AccPrivate\n");2856if(superROM->modifiers & J9AccProtected) printf("\tsuperMethod is J9AccProtected\n");2857if(superROM->modifiers & J9AccPublic) printf("\tsuperMethod is J9AccPublic\n");2858if(superROM->modifiers & J9AccStatic) printf("\tsuperMethod is J9AccStatic\n");2859if(superROM->modifiers & J9AccStrict) printf("\tsuperMethod is J9AccStrict\n");2860if(superROM->modifiers & J9AccSuper) printf("\tsuperMethod is J9AccSuper\n");2861if(superROM->modifiers & J9AccSynchronized) printf("\tsuperMethod is J9AccSynchronized\n");2862if(superROM->modifiers & J9AccSynthetic) printf("\tsuperMethod is J9AccSynthetic\n");2863if(superROM->modifiers & J9AccTransient) printf("\tsuperMethod is J9AccTransient\n");2864if(superROM->modifiers & J9AccVarArgs) printf("\tsuperMethod is J9AccVarArgs\n");2865if(superROM->modifiers & J9AccVolatile) printf("\tsuperMethod is J9AccVolatile\n");28662867fflush(stdout);2868}28692870if((subMethod != superMethod) && methodModifiersAreSafe && (J9_BYTECODE_END_FROM_ROM_METHOD(subROM) - J9_BYTECODE_START_FROM_ROM_METHOD(subROM))>0 ) //If the j9methods don't match, method has been overridden2871{2872if (traceIt)2873{2874printf("For submethod %p, trying to match signature for overridden bit\n",subMethod);2875fflush(stdout);2876}287728782879const uint8_t * _code = subMethod->bytecodes; //a pointer to bytecodes2880bool matches=false;2881bool finishedArgs = false;2882int32_t curLocalSize;2883int32_t i = 0;2884uint16_t cpIndex = 0;2885for (int32_t nextLocalIndex = 0; !matches && !finishedArgs && nextLocalIndex<255; nextLocalIndex += curLocalSize)2886{2887curLocalSize = 1;2888switch (TR_J9ByteCodeIterator::convertOpCodeToByteCodeEnum(_code[i++]))2889{2890case J9BCaload0:2891finishedArgs = (nextLocalIndex != 0);2892break;2893case J9BClload1: case J9BCdload1:2894curLocalSize = 2;2895// fall through2896case J9BCiload1: case J9BCfload1: case J9BCaload1:2897finishedArgs = (nextLocalIndex != 1);2898break;2899case J9BClload2: case J9BCdload2:2900curLocalSize = 2;2901// fall through2902case J9BCiload2: case J9BCfload2: case J9BCaload2:2903finishedArgs = (nextLocalIndex != 2);2904break;2905case J9BClload3: case J9BCdload3:2906curLocalSize = 2;2907// fall through2908case J9BCiload3: case J9BCfload3: case J9BCaload3:2909finishedArgs = (nextLocalIndex != 3);2910break;2911case J9BClload: case J9BCdload:2912curLocalSize = 2;2913// fall through2914case J9BCiload: case J9BCfload: case J9BCaload:2915finishedArgs = (nextLocalIndex != _code[i++]);2916break;2917case J9BCinvokespecial:2918cpIndex = BC_OP_U16(&_code[i]); //will need to compare signature with superMethod.2919matches=true;2920break;2921case J9BCinvokespecialsplit:2922cpIndex = *(U_16*)(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(ROMCl) + BC_OP_U16(&_code[i])); //will need to compare signature with superMethod.2923matches=true;2924break;2925default:2926finishedArgs = true;2927break;2928}2929}29302931J9UTF8 * callSignature;2932J9UTF8 * callName;2933if(matches) //so far we are matching our pattern2934{2935if (traceIt)2936{2937printf("For submethod %p, pattern matches after bc walk\n",subMethod);2938fflush(stdout);2939}294029412942J9ROMFieldRef * ref1 = &(((J9ROMFieldRef *)((char *)ROMCl+sizeof(J9ROMClass)))[cpIndex]);2943J9ROMNameAndSignature *nameAndSignature = J9ROMFIELDREF_NAMEANDSIGNATURE(ref1); //this isn't a string its a struct.2944callSignature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSignature);2945callName = J9ROMNAMEANDSIGNATURE_NAME(nameAndSignature);29462947J9UTF8 *superSignature = J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod));2948J9UTF8 *superName = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod));29492950if( J9UTF8_LENGTH(superSignature) != J9UTF8_LENGTH(callSignature)2951|| J9UTF8_LENGTH(superName) != J9UTF8_LENGTH(callName)2952|| !(strncmp((char *)J9UTF8_DATA(superSignature),(char *)J9UTF8_DATA(callSignature),J9UTF8_LENGTH(superSignature))==0)2953|| !(strncmp((char *)J9UTF8_DATA(superName),(char *)J9UTF8_DATA(callName),J9UTF8_LENGTH(superSignature))==0) )29542955{2956if (traceIt)2957{2958printf("For submethod %p,signature compare fails after bc walk superSiglen = %d subsiglen = %d supernamelen = %d subnamelen =%d\n"2959,subMethod,J9UTF8_LENGTH(superSignature),J9UTF8_LENGTH(callSignature),J9UTF8_LENGTH(superName),J9UTF8_LENGTH(callName));2960fflush(stdout);2961}2962matches=false;2963}2964else2965{2966uint8_t opcode = _code[i+2]; //an invokespecial takes up 3 bytes.. we point at second byte after for loop, so increment by 22967TR_J9ByteCode bc = TR_J9ByteCodeIterator::convertOpCodeToByteCodeEnum(opcode);2968if(bc != J9BCgenericReturn || &(_code[i+3]) != J9_BYTECODE_END_FROM_ROM_METHOD(subROM)) //second condition ensures that the return is the last bytecode. See defect 148222.2969{2970if (traceIt)2971{2972printf("For submethod %p,signature compare fails after bc walk bc !=genericReturn at i(%d)+2\n", subMethod, i);2973fflush(stdout);2974}2975matches=false;2976}2977}2978}29792980if(!matches) //matches is false if method is overridden.2981{2982jitUpdateMethodOverride(vm, cl, superMethod,subMethod);2983vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, superMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);29842985if (traceIt)2986{2987printf("For submethod %p, pattern does not match after sig compares.\n",subMethod);2988fflush(stdout);2989}299029912992//Updating all grandparent classes overridden bits2993J9Class * tempsuperCl;2994J9VTableHeader * tempsuperVTableHeader;2995J9Method ** tempsuperVTable;2996J9Method * tempsuperMethod;2997intptr_t tempmethodCount;2998for(int32_t k=classDepth-1;k>=0;k--)2999{30003001tempsuperCl = cl->superclasses[k];3002tempsuperVTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(tempsuperCl);3003tempmethodCount = (intptr_t)tempsuperVTableHeader->size;30043005if(methodIndex>= tempmethodCount) //we are outside the grandparent's vft slots3006break;30073008tempsuperVTable = J9VTABLE_FROM_HEADER(tempsuperVTableHeader);3009tempsuperVTable = tempsuperVTable + methodIndex;3010tempsuperMethod= *tempsuperVTable;3011jitUpdateMethodOverride(vm, cl, tempsuperMethod,subMethod);3012vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, tempsuperMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);3013}3014}3015else3016{3017if (traceIt)3018{3019printf("For submethod %p, determined it is not overridden by bytecode walk and signature compare\n",subMethod);3020fflush(stdout);3021}3022}3023}3024else if (superMethod != subMethod) // we don't have bytecodes, but the j9methods don't match, so set the overridden bit anyways3025{3026jitUpdateMethodOverride(vm, cl, superMethod,subMethod);3027vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, superMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);30283029if (traceIt)3030{3031printf("For submethod %p, j9methods don't match. Setting overridden bit. endbc - startbc = %" OMR_PRIdPTR " methodmodifiersaresafe = %d\n",subMethod,(J9_BYTECODE_END_FROM_ROM_METHOD(subROM) - J9_BYTECODE_START_FROM_ROM_METHOD(subROM)),methodModifiersAreSafe);3032fflush(stdout);3033}303430353036//Updating all grandparent classes overridden bits3037J9Class * tempsuperCl;3038J9VTableHeader * tempsuperVTableHeader;3039J9Method ** tempsuperVTable;3040J9Method * tempsuperMethod;3041intptr_t tempmethodCount;3042for(int32_t k=classDepth-1;k>=0;k--)3043{30443045tempsuperCl = cl->superclasses[k];3046tempsuperVTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(tempsuperCl);3047tempmethodCount = (intptr_t)tempsuperVTableHeader->size;30483049if(methodIndex >= tempmethodCount) //we are outside the grandparent's vft slots3050break;30513052tempsuperVTable = J9VTABLE_FROM_HEADER(tempsuperVTableHeader);3053tempsuperVTable = tempsuperVTable + methodIndex;3054tempsuperMethod= *tempsuperVTable;30553056jitUpdateMethodOverride(vm, cl, tempsuperMethod,subMethod);3057vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, tempsuperMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);3058}30593060}30613062methodIndex++;3063}3064}3065}30663067static bool updateCHTable(J9VMThread * vmThread, J9Class * cl)3068{3069typedef void JIT_METHOD_OVERRIDE_UPDATE(J9VMThread *, J9Class *, J9Method *, J9Method *);30703071JIT_METHOD_OVERRIDE_UPDATE * callBack = jitUpdateMethodOverride;3072bool updateFailed = false;30733074{3075J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;30763077TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);30783079#if defined(J9VM_OPT_JITSERVER)3080TR_ASSERT_FATAL(compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER, "updateCHTable() should not be called on JITServer!\n");3081#endif30823083TR_PersistentCHTable * table = 0;3084if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))3085table = compInfo->getPersistentInfo()->getPersistentCHTable();30863087TR_J9VMBase *vm = TR_J9VMBase::get(jitConfig, vmThread);3088TR_OpaqueClassBlock *clazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(cl);30893090char *name; int32_t len;3091bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassLoading);3092if (p)3093{3094name = vm->getClassNameChars(clazz, len);3095TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "--updt-- %.*s\n", len, name);3096}30973098int32_t classDepth = J9CLASS_DEPTH(cl) - 1;3099if (classDepth >= 0)3100{3101J9Class * superCl = cl->superclasses[classDepth];3102superCl->classDepthAndFlags |= J9AccClassHasBeenOverridden;31033104TR_OpaqueClassBlock *superClazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(superCl);3105if (p)3106{3107name = vm->getClassNameChars(superClazz, len);3108TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "\textending %.*s\n", len, name);3109}3110if (table)3111{3112if (!table->classGotExtended(vm, compInfo->persistentMemory(), superClazz, clazz))3113updateFailed = true;3114}3115for (J9ITable * iTableEntry = (J9ITable *)cl->iTable; iTableEntry; iTableEntry = iTableEntry->next)3116{3117superCl = iTableEntry->interfaceClass;3118if (superCl != cl)3119{3120superCl->classDepthAndFlags |= J9AccClassHasBeenOverridden;3121superClazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(superCl);3122if (p)3123{3124name = vm->getClassNameChars(superClazz, len);3125TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "\textending interface %.*s\n", len, name);3126}3127if (table)3128{3129if (!table->classGotExtended(vm, compInfo->persistentMemory(), superClazz, clazz))3130updateFailed = true;3131}3132}3133}3134}3135}3136// method override3137if(!TR::Options::getCmdLineOptions()->getOption(TR_DisableNewMethodOverride))3138updateOverriddenFlag(vmThread,cl);3139else3140jitUpdateInlineAttribute(vmThread, cl, (void *)callBack);314131423143return !updateFailed;3144}31453146void turnOffInterpreterProfiling(J9JITConfig *jitConfig);3147314831493150/**3151* @brief A function to get the available virtual memory.3152*3153* Note: Only supported for 32 bit Windows in Production3154* Code currently runs under PROD_WITH_ASSUMES in 31/32 bit Linux and 31 bit z/OS but3155* returns -1 (error) to prevent any decision making3156*3157* @param compInfo TR::CompilationInfo needed for getting Port Access3158* @param vmThread J9VMThread needed for tracepoints3159* @param availableVirtualMemoryMB Pointer to availableVirtualMemoryKB3160* @return 0 if success, -1 if error3161*/3162int32_t getAvailableVirtualMemoryMB(TR::CompilationInfo *compInfo, J9VMThread *vmThread, uint32_t *availableVirtualMemoryMB)3163{3164TRC_JIT_getAvailableVirtualMemoryMBEnter(vmThread);3165#if defined(TR_TARGET_32BIT)31663167#if defined(WINDOWS)3168J9MemoryInfo memInfo;3169PORT_ACCESS_FROM_JITCONFIG(compInfo->getJITConfig());3170if (j9sysinfo_get_memory_info(&memInfo) != 0 ||3171memInfo.availVirtual == J9PORT_MEMINFO_NOT_AVAILABLE)3172{3173TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3174return -1; // error case3175}3176*availableVirtualMemoryMB = (uint32_t)(memInfo.availVirtual >> 20); // conversion to uint32_t is safe on 32-bit OS31773178if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitMemory))3179{3180uint32_t totalVirtualMemoryMB = (uint32_t)(memInfo.totalVirtual >> 20);3181uint32_t virtualMemoryUsedMB = totalVirtualMemoryMB - *availableVirtualMemoryMB;31823183TR_VerboseLog::writeLineLocked(TR_Vlog_MEMORY, "Virtual Memory Used: %d MB out of %d MB", virtualMemoryUsedMB, totalVirtualMemoryMB);3184}31853186TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3187return 0;3188#elif defined(LINUX)31893190// Having TR::Options::_userSpaceVirtualMemoryMB < 1 means to determine the3191// userspace size dynamically. However this isn't implemented on Linux so3192// the function returns -13193if (TR::Options::_userSpaceVirtualMemoryMB < 0)3194{3195TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3196return -1;3197}31983199uint32_t totalVirtualMemoryMB = (uint32_t)TR::Options::_userSpaceVirtualMemoryMB;32003201/*3202See http://man7.org/linux/man-pages/man5/proc.5.html or run "man proc" for information on the3203/proc pseudo filesystem. The file we're using to get the virtual memory information3204is /proc/self/status. A small glimpse into the file:32053206...3207Utrace: 03208FDSize: 2563209Groups: 476297 478112 819790 837093 887132 9035973210VmPeak: 99044 kB3211VmSize: 99044 kB3212VmLck: 0 kB3213...32143215We are interested in the VmSize field3216*/32173218::FILE* statFile = fopen("/proc/self/status", "r");3219if (statFile)3220{3221static const int bufferSize = 1024;3222char buffer[bufferSize];3223bool foundVirtualMemory = false;3224int bufferStartIndex = 0;32253226while (!foundVirtualMemory && !feof(statFile))3227{3228if (!fgets(buffer,bufferSize,statFile))3229break;32303231if (buffer[0] == 'V')3232{3233/* Check if we have the right field, namely "VmSize" */3234if (buffer[1] == 'm'3235&& buffer[2] == 'S'3236&& buffer[3] == 'i'3237&& buffer[4] == 'z'3238&& buffer[5] == 'e'3239&& buffer[6] == ':')3240{3241int bufferIndex = 0;32423243/* skip whitespace until we hit the first number */3244while (bufferIndex < bufferSize && buffer[bufferIndex] != '\0' && (buffer[bufferIndex] < '0' || buffer[bufferIndex] > '9'))3245bufferIndex++;32463247/* Out of bounds check */3248if (bufferIndex == bufferSize || buffer[bufferIndex] == '\0')3249break;32503251bufferStartIndex = bufferIndex;32523253/* Determine the end of the number */3254while (bufferIndex < bufferSize && buffer[bufferIndex] >= '0' && buffer[bufferIndex] <= '9')3255bufferIndex++;32563257/* Bounds and sanity check */3258if ((bufferIndex + 2) < bufferSize3259&& (bufferIndex - bufferStartIndex + 1) < 93260&& buffer[bufferIndex] == ' '3261&& buffer[bufferIndex + 1] == 'k'3262&& buffer[bufferIndex + 2] == 'B')3263{3264buffer[bufferIndex] = '\0';3265foundVirtualMemory = true;3266}3267else3268break;3269}3270} // if (buffer[0] == 'V')3271} // while(!feof(statFile) && !foundVirtualMemory && !error)32723273fclose(statFile);32743275if (!foundVirtualMemory)3276{3277TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3278return -1; // error case3279}32803281uint32_t virtualMemoryUsedMB = (uint32_t)(atoi(&buffer[bufferStartIndex]) >> 10);32823283// Check if amount read from the file is less than or equal to the total virtual memory3284if (totalVirtualMemoryMB >= virtualMemoryUsedMB)3285*availableVirtualMemoryMB = totalVirtualMemoryMB - virtualMemoryUsedMB;3286else3287{3288TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3289return -1; // error case3290}32913292// Always return -1 to test this code out3293TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3294if (TR::Options::getCmdLineOptions()->getOption(TR_EnableLowerCompilationLimitsDecisionMaking))3295return 0;3296else3297return -1;32983299} // if (statFile)3300else3301{3302TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3303return -1; // error case3304}33053306#elif defined(J9ZOS390)33073308/*33093310In 31 bit z/OS, the address space is structured as follows:33113312LOCAL STORAGE MAP3313___________________________3314| |80000000 <- Top of Ext. Private3315| Extended |3316| LSQA/SWA/229/230 |80000000 <- Max Ext. User Region Address3317|___________________________|77636000 <- ELSQA Bottom3318| |3319| (Free Extended Storage) |3320|___________________________|289B8000 <- Ext. User Region Top3321| |3322| Extended User Region |3323|___________________________|25200000 <- Ext. User Region Start3324: :3325: Extended Global Storage :3326=======================================<- 16M Line3327: Global Storage :3328:___________________________: 900000 <- Top of Private3329| |3330| LSQA/SWA/229/230 | 900000 <- Max User Region Address3331|___________________________| 821000 <- LSQA Bottom3332| |3333| (Free Storage) |3334|___________________________| 4B000 <- User Region Top3335| |3336| User Region |3337|___________________________| 6000 <- User Region Start3338: System Storage :3339:___________________________: 033403341The exact addresses may vary from system to system (with the exception of the "Top of Private" and "Top of Ext. Private"3342which generally stay the same). The System Storage, LSQA, Global Storage, Extended Global Storage, and Extended LSQA cannot be3343allocated. Thus the total userspace available can be approximated by doing:3344(Max Ext. User Region Address - (Ext. User Region Start - Max User Region Address))33453346The amount of memory used can be determined by the __heaprpt() function.33473348*/33493350// Determine how much memory is being used3351hreport_t heapReport;33523353if (__heaprpt(&heapReport) != 0)3354{3355TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3356return -1; // error case3357}33583359uint32_t virtualMemoryUsedMB = (uint32_t)(heapReport.__uheap_bytes_alloc >> 20);33603361// Determine how much memory is available3362if (TR::Options::_userSpaceVirtualMemoryMB > 0)3363{3364if (TR::Options::_userSpaceVirtualMemoryMB >= virtualMemoryUsedMB)3365*availableVirtualMemoryMB = (uint32_t)TR::Options::_userSpaceVirtualMemoryMB - virtualMemoryUsedMB;3366else3367{3368TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3369return -1;3370}3371}3372else // Use Dynamically determined user space3373{3374// A pointer to the current ASCB is located at offset PSAAOLD in the PSA3375void *ascb = (void *)(*((uint32_t *)PSAAOLD));33763377// A pointer to the LDA is located at offset ASCBLDA in the ASCB3378struct LDA *lda = (struct LDA *)(*((uint32_t *)((uint32_t)ascb + ASCBLDA)));33793380if (!lda)3381{3382TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3383return -1;3384}33853386// Determine how much of the 2 GB address space is user space3387void *maxUserRegionAddress = (void*)((uint32_t)(lda->strta) + lda->siza);3388void *maxExtUserRegionAddress = (void*)((uint32_t)(lda->estra) + lda->esiza);3389uint32_t totalVirtualMemoryMB = ((uint32_t)maxExtUserRegionAddress - ((uint32_t)(lda->estra) - (uint32_t)maxUserRegionAddress)) >> 20;33903391if (totalVirtualMemoryMB >= virtualMemoryUsedMB)3392*availableVirtualMemoryMB = totalVirtualMemoryMB - virtualMemoryUsedMB;3393else3394{3395TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3396return -1;3397}3398}33993400// Always return -1 to test this code out3401TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3402if (TR::Options::getCmdLineOptions()->getOption(TR_EnableLowerCompilationLimitsDecisionMaking))3403return 0;3404else3405return -1;34063407#else // Unsupported platforms3408TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3409return -1;3410#endif34113412#else // Not 32 bit3413TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);3414return -1;3415#endif //#if defined(TR_TARGET_32BIT)3416}34173418/**3419* @brief A function to lower compilation limits when the JIT detects low virtual memory remaining3420*3421* 32-bit Windows due to low 2GB virtual space limit available to user mode3422*3423* When the available virtual memory is too small we may reduce some compilation3424* parameters like: scratchSpaceLimit, number of compilation threads, optServer, GCR3425*3426* @param compInfo TR::CompilationInfo needed for getting Port Access3427* @param vmThread Current thread3428*/3429void lowerCompilationLimitsOnLowVirtualMemory(TR::CompilationInfo *compInfo, J9VMThread *vmThread)3430{3431#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))3432// Mechanism to disable this function3433if (0 == TR::Options::_userSpaceVirtualMemoryMB)3434return;34353436uint32_t availableVirtualMemoryMB;34373438int32_t rc = getAvailableVirtualMemoryMB(compInfo, vmThread, &availableVirtualMemoryMB);34393440if (rc)3441return; //error case34423443if ((availableVirtualMemoryMB < (uint32_t)TR::Options::getLowVirtualMemoryMBThreshold()/2) ||3444(availableVirtualMemoryMB < (uint32_t)TR::Options::getLowVirtualMemoryMBThreshold() &&3445compInfo->getPersistentInfo()->getNumLoadedClasses() >= TR::Options::_bigAppThreshold))3446{3447uint32_t crtTime = (uint32_t)compInfo->getPersistentInfo()->getElapsedTime(); // 49 days resolution through casting3448static bool traceSent = false;3449// Generate a trace point3450if (TrcEnabled_Trc_JIT_LowUserVirtualMemory && !traceSent)3451{3452traceSent = true; // prevent multiple messages to the trace file3453// Do I know the thread?3454if (vmThread)3455{3456// Generate a trace point3457Trc_JIT_LowUserVirtualMemory(vmThread, availableVirtualMemoryMB);3458}3459}34603461// Decrease the scratch space limit3462if (TR::Options::getScratchSpaceLimit() > TR::Options::getScratchSpaceLimitKBWhenLowVirtualMemory()*1024)3463{3464TR::Options::setScratchSpaceLimit(TR::Options::getScratchSpaceLimitKBWhenLowVirtualMemory() * 1024);3465if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))3466{3467TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: changed scratchSpaceLimit to %d KB because VMemAv=%u MB",3468crtTime, TR::Options::getScratchSpaceLimit() / 1024, availableVirtualMemoryMB);3469}3470}34713472// Shut down all compilation threads but one3473if (!compInfo->getRampDownMCT())3474{3475compInfo->setRampDownMCT();3476if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))3477{3478TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%u setRampDownMCT because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);3479}3480}34813482bool doDisableGCR = false;3483if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations))3484{3485TR::Options::getAOTCmdLineOptions()->setOption(TR_DisableGuardedCountingRecompilations);3486doDisableGCR = true;3487}3488if (!TR::Options::getJITCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations))3489{3490TR::Options::getJITCmdLineOptions()->setOption(TR_DisableGuardedCountingRecompilations);3491doDisableGCR = true;3492}3493if (doDisableGCR && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))3494{3495TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: GCR disabled because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);3496}34973498// Disable server mode3499bool doDisableServerMode = false;3500if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoOptServer))3501{3502TR::Options::getAOTCmdLineOptions()->setOption(TR_NoOptServer);3503doDisableServerMode = true;3504}3505if (!TR::Options::getJITCmdLineOptions()->getOption(TR_NoOptServer))3506{3507TR::Options::getJITCmdLineOptions()->setOption(TR_NoOptServer);3508doDisableServerMode = true;3509}3510if (doDisableServerMode && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))3511{3512TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: server mode disabled because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);3513}35143515// Turn off interpreter profiling3516turnOffInterpreterProfiling(compInfo->getJITConfig());35173518// Disable all future non-essential compilations if virtual memory is really low3519{3520compInfo->getPersistentInfo()->setDisableFurtherCompilation(true);3521if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))3522{3523TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: Disable non-essential compilations because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);3524}3525}3526}3527#endif //#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))3528}352935303531J9Method * getNewInstancePrototype(J9VMThread * context);35323533static void getClassNameIfNecessary(TR_J9VMBase *vm, TR_OpaqueClassBlock *clazz, char *&className, int32_t &len)3534{3535if (className == NULL)3536className = vm->getClassNameChars(clazz, len);3537}35383539static bool chTableOnClassLoad(J9VMThread *vmThread, TR_OpaqueClassBlock *clazz, TR::CompilationInfo *compInfo, TR_J9VMBase *vm)3540{3541J9Class *cl = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz);3542bool allocFailed = false;35433544if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts)3545#if defined(J9VM_OPT_JITSERVER)3546&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER3547#endif3548)3549{3550TR_PersistentClassInfo *info = compInfo->getPersistentInfo()->getPersistentCHTable()->classGotLoaded(vm, clazz);35513552if (info)3553{3554// If its an interface class it won't be initialized, so we have to update the CHTable now.3555// Otherwise, we will update the CHTable once the class gets initialized (i.e. live)3556//3557if (vm->isInterfaceClass(clazz))3558{3559if (!updateCHTable(vmThread, cl))3560{3561allocFailed = true;3562compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, clazz, info, true);3563}3564}3565else if (vm->isClassArray(clazz))3566{3567if (!compInfo->getPersistentInfo()->getPersistentCHTable()->classGotInitialized(vm, compInfo->persistentMemory(), clazz))3568{3569TR_PersistentClassInfo *arrayClazzInfo = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfo(clazz);3570if (arrayClazzInfo)3571compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, clazz, arrayClazzInfo, false);3572}3573TR_OpaqueClassBlock *compClazz = vm->getComponentClassFromArrayClass(clazz);3574if (compClazz)3575{3576TR_PersistentClassInfo *clazzInfo = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfo(compClazz);3577if (clazzInfo && !clazzInfo->isInitialized())3578{3579bool initFailed = false;3580if (!compInfo->getPersistentInfo()->getPersistentCHTable()->classGotInitialized(vm, compInfo->persistentMemory(), compClazz))3581initFailed = true;35823583if (!initFailed &&3584!vm->isClassArray(compClazz) &&3585!vm->isInterfaceClass(compClazz) &&3586!vm->isPrimitiveClass(compClazz))3587initFailed = !updateCHTable(vmThread, ((J9Class *) compClazz));35883589if (initFailed)3590{3591compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, compClazz, clazzInfo, false);3592allocFailed = true;3593}3594}3595}3596}3597}3598else3599allocFailed = true;3600}36013602return allocFailed;3603}36043605static void checkForLockReservation(J9VMThread *vmThread,3606J9JITConfig *jitConfig,3607J9ClassLoader *classLoader,3608TR_OpaqueClassBlock *clazz,3609TR_J9VMBase *vm,3610TR::CompilationInfo *compInfo,3611char * className,3612int32_t classNameLen)3613{3614TR::Options * options = TR::Options::getCmdLineOptions();3615if (options->getOption(TR_ReservingLocks)3616#if defined(J9VM_OPT_JITSERVER)3617&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER3618#endif3619)3620{3621J9Class *cl = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz);3622TR_J9VMBase *fej9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, 0));3623int lwOffset = fej9->getByteOffsetToLockword(clazz);3624if (lwOffset > 0)3625{3626bool reserve = options->getOption(TR_ReserveAllLocks);36273628if (!reserve && ((J9JavaVM *)vmThread->javaVM)->systemClassLoader == classLoader)3629{3630getClassNameIfNecessary(vm, clazz, className, classNameLen);3631if (classNameLen == 22 && !strncmp(className, "java/lang/StringBuffer", 22))3632reserve = true;3633else if (classNameLen == 16 && !strncmp(className, "java/util/Random", 16))3634reserve = true;3635}36363637TR::SimpleRegex *resRegex = options->getLockReserveClass();3638if (!reserve && resRegex != NULL)3639{3640getClassNameIfNecessary(vm, clazz, className, classNameLen);3641if (TR::SimpleRegex::match(resRegex, className))3642reserve = true;3643}36443645if (reserve)3646{3647TR_PersistentClassInfo *classInfo = compInfo3648->getPersistentInfo()3649->getPersistentCHTable()3650->findClassInfo(clazz);36513652if (classInfo != NULL)3653{3654classInfo->setReservable();3655if (!TR::Options::_aggressiveLockReservation)3656J9CLASS_EXTENDED_FLAGS_SET(cl, J9ClassReservableLockWordInit);3657}3658}3659}3660}3661}36623663void jitHookClassLoadHelper(J9VMThread *vmThread,3664J9JITConfig * jitConfig,3665J9Class * cl,3666TR::CompilationInfo *compInfo,3667UDATA *classLoadEventFailed)3668{3669bool allocFailed = false;3670TR_J9VMBase *vm = TR_J9VMBase::get(jitConfig, vmThread);3671TR_OpaqueClassBlock *clazz = TR::Compiler->cls.convertClassPtrToClassOffset(cl);3672jitAcquireClassTableMutex(vmThread);36733674compInfo->getPersistentInfo()->incNumLoadedClasses();36753676if (compInfo->getPersistentInfo()->getNumLoadedClasses() == TR::Options::_bigAppThreshold)3677{3678#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))3679// When we reach the bigAppThreshold limit we examine the available virtual memory3680// and if this is too small we reduce some compilation parameters like:3681// scratchSpaceLimit, number of compilation threads, optServer, GCR3682lowerCompilationLimitsOnLowVirtualMemory(compInfo, vmThread);3683#endif3684// For large applications be more conservative with hot compilations3685if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableConservativeHotRecompilationForServerMode))3686{3687TR::Options::_sampleThreshold /= 3; // divide by 3 to become more conservative (3% instead of 1%)3688TR::Options::_resetCountThreshold /= 3;3689if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))3690{3691TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u INFO: Changed sampleThreshold to %d",3692(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), TR::Options::_sampleThreshold);3693}3694}3695}36963697// todo: why is the override bit on already....temporarily reset it3698// ALI 20031015: I think I have fixed the above todo - we should never3699// get an inconsistent state now. The following should be unnecessary -3700// verify and remove FIXME3701cl->classDepthAndFlags &= ~J9AccClassHasBeenOverridden;37023703// For regular classes, cl->classLoader points to the correct class loader by the time we enter this hook.3704// For anonymous classes however, it points to the anonymous class loader and not the correct class loader.3705// Once the class is fully loaded the classLoader member will be updated to point to the correct class loader,3706// which is the anonymous class's host class's class loader, but that doesn't do us any good in this hook.3707// We need the correct class loader right now, so we grab the host class's class loader instead.3708// For regular classes, cl->hostClass points back to the class itself, so by doing this we get the correct3709// class loader for both regular and anonymous classes without having to check if this is an anonymous class.3710J9ClassLoader *classLoader = cl->hostClass->classLoader;37113712bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassLoading);3713char * className = NULL;3714int32_t classNameLen = -1;3715if (p)3716{3717getClassNameIfNecessary(vm, clazz, className, classNameLen);3718TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "--load-- loader %p, class %p : %.*s\n", classLoader, cl, classNameLen, className);3719}37203721// add the newInstance hook3722#if defined(J9ZOS390)3723cl->romableAotITable = (UDATA) TOC_UNWRAP_ADDRESS((void *)&jitTranslateNewInstanceMethod);3724#elif defined(TR_HOST_POWER) && (defined(TR_HOST_64BIT) || defined(AIXPPC)) && !defined(__LITTLE_ENDIAN__)3725cl->romableAotITable = (UDATA) (*(void **)jitTranslateNewInstanceMethod);3726#else3727cl->romableAotITable = (UDATA) jitTranslateNewInstanceMethod;3728#endif37293730if (((J9JavaVM *)vmThread->javaVM)->systemClassLoader != classLoader)3731{3732TR::Options::_numberOfUserClassesLoaded ++;3733}37343735compInfo->getPersistentInfo()->getPersistentClassLoaderTable()->associateClassLoaderWithClass(vmThread, classLoader, clazz);37363737// Update the count for the newInstance3738//3739TR::Options * options = TR::Options::getCmdLineOptions();3740if (options->anOptionSetContainsACountValue())3741{3742J9Method *method = getNewInstancePrototype(vmThread);3743if (method)3744{3745TR::OptionSet * optionSet = findOptionSet(method, false);3746if (optionSet)3747options = optionSet->getOptions();3748}3749}3750//fprintf(stderr, "Will set the count for NewInstancePrototype to %d\n", options->getInitialCount());3751cl->newInstanceCount = options->getInitialCount();37523753allocFailed = chTableOnClassLoad(vmThread, clazz, compInfo, vm);37543755compInfo->getPersistentInfo()->ensureUnloadedAddressSetsAreInitialized();3756// TODO: change the above line to something like the following in order to handle allocation failures:3757// if (!allocFailed)3758// allocFailed = !compInfo->getPersistentInfo()->ensureUnloadedAddressSetsAreInitialized();37593760*classLoadEventFailed = allocFailed;37613762// Determine whether this class gets lock reservation3763checkForLockReservation(vmThread, jitConfig, classLoader, clazz, vm, compInfo, className, classNameLen);37643765jitReleaseClassTableMutex(vmThread);3766}37673768static void jitHookClassLoad(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)3769{3770J9VMInternalClassLoadEvent * classLoadEvent = (J9VMInternalClassLoadEvent *)eventData;3771J9VMThread * vmThread = classLoadEvent->currentThread;3772J9Class * cl = classLoadEvent->clazz;3773J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;3774if (jitConfig == 0)3775return; // if a hook gets called after freeJitConfig then not much else we can do37763777TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);3778TR_PersistentCHTable * cht = NULL;3779if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))3780cht = compInfo->getPersistentInfo()->getPersistentCHTable();3781if (cht && !cht->isActive())3782return;37833784getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "class load");37853786jitHookClassLoadHelper(vmThread, jitConfig, cl, compInfo, &(classLoadEvent->failed));3787}37883789int32_t loadingClasses;37903791static bool chTableOnClassPreinitialize(J9VMThread *vmThread,3792J9Class *cl,3793TR_OpaqueClassBlock *clazz,3794TR::CompilationInfo *compInfo,3795TR_J9VMBase *vm)3796{3797bool initFailed = false;37983799#if defined(J9VM_OPT_JITSERVER)3800if (compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER)3801#endif3802{3803if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))3804{3805if (!initFailed && !compInfo->getPersistentInfo()->getPersistentCHTable()->classGotInitialized(vm, compInfo->persistentMemory(), clazz))3806initFailed = true;38073808if (!initFailed &&3809!vm->isInterfaceClass(clazz))3810updateCHTable(vmThread, cl);3811}3812else3813{3814if (!initFailed && !updateCHTable(vmThread, cl))3815initFailed = true;3816}38173818if (initFailed)3819{3820TR_PersistentClassInfo *info = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfo(clazz);3821compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, clazz, info, false);3822}3823}38243825return initFailed;3826}38273828void jitHookClassPreinitializeHelper(J9VMThread *vmThread,3829J9JITConfig *jitConfig,3830J9Class *cl,3831UDATA *classPreinitializeEventFailed)3832{3833TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);3834TR_J9VMBase *vm = TR_J9VMBase::get(jitConfig, vmThread);3835TR_OpaqueClassBlock *clazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(cl);3836bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassLoading);3837if (p)3838{3839int32_t len;3840char * className = vm->getClassNameChars(clazz, len);3841TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "--init-- %.*s\n", len, className);3842}38433844jitAcquireClassTableMutex(vmThread);38453846*classPreinitializeEventFailed = chTableOnClassPreinitialize(vmThread, cl, clazz, compInfo, vm);38473848jitReleaseClassTableMutex(vmThread);3849}385038513852/// This routine is used to indicate successful initialization of the J9Class3853/// before any Java code (<clinit>) is run. When analyzing code in the <clinit>3854/// with CHTable assumptions, this ensures that the CHTable is updated correctly.3855/// Otherwise a class will not be seen as having been initialized in the Java code3856/// reachable from the <clinit>; causing possibly incorrect devirtualization or other3857/// CHTable opts to be applied in a method called by <clinit> (if the <clinit> for class C calls a3858/// virtual method on an object of class C which is instantiated in the code reachable3859/// from <clinit> (this was an actual WSAD scenario)).3860///3861static void jitHookClassPreinitialize(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)3862{3863J9VMClassPreinitializeEvent * classPreinitializeEvent = (J9VMClassPreinitializeEvent *)eventData;3864J9VMThread * vmThread = classPreinitializeEvent->currentThread;3865J9Class * cl = classPreinitializeEvent->clazz;38663867J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;3868if (jitConfig == 0)3869return; // if a hook gets called after freeJitConfig then not much else we can do38703871loadingClasses = true;38723873TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);3874TR_PersistentCHTable * cht = NULL;3875if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))3876cht = compInfo->getPersistentInfo()->getPersistentCHTable();3877if (cht && !cht->isActive())3878return;38793880jitHookClassPreinitializeHelper(vmThread, jitConfig, cl, &(classPreinitializeEvent->failed));3881}38823883static void jitHookClassInitialize(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)3884{3885J9VMClassInitializeEvent * classInitializeEvent = (J9VMClassInitializeEvent *)eventData;3886J9VMThread * vmThread = classInitializeEvent->currentThread;3887J9Class * cl = classInitializeEvent->clazz;38883889J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;3890if (jitConfig == 0)3891return; // if a hook gets called after freeJitConfig then not much else we can do38923893loadingClasses = false;3894}38953896int32_t returnIprofilerState()3897{3898#if defined(J9VM_INTERP_PROFILING_BYTECODES)3899return interpreterProfilingState;3900#else3901return IPROFILING_STATE_OFF;3902#endif3903}39043905#if defined(J9VM_INTERP_PROFILING_BYTECODES)39063907#define TEST_verbose 03908#define TEST_events 03909#define TEST_records 039103911void turnOffInterpreterProfiling(J9JITConfig *jitConfig)3912{3913// Turn off interpreter profiling3914//3915if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))3916{3917if (interpreterProfilingState != IPROFILING_STATE_OFF)3918{3919interpreterProfilingState = IPROFILING_STATE_OFF;3920J9HookInterface ** hook = jitConfig->javaVM->internalVMFunctions->getVMHookInterface(jitConfig->javaVM);3921(*hook)->J9HookUnregister(hook, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, NULL);39223923PORT_ACCESS_FROM_JITCONFIG(jitConfig);3924if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))3925{3926TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);3927TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler stopped", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime());3928}3929}3930}3931}39323933/// The following two methods (stopInterpreterProfiling and restartInterpreterProfiling)3934/// are used when we disable/enable JIT compilation at runtime3935/// @{3936void stopInterpreterProfiling(J9JITConfig *jitConfig)3937{3938// Turn off interpreter profiling3939//3940if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))3941{3942turnOffInterpreterProfiling(jitConfig);3943TR::Options::getCmdLineOptions()->setOption(TR_DisableInterpreterProfiling, true);3944}3945}39463947void restartInterpreterProfiling()3948{3949if (interpreterProfilingWasOnAtStartup && TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))3950{3951TR::Options::getCmdLineOptions()->setOption(TR_DisableInterpreterProfiling, false);3952// The hook for interpreter profiling will be registered when a class load phase is detected3953// We could more fancy and memorize the state of interpreter profiling3954// and revert to the old state.3955}3956}39573958/// @}39593960static bool checkAndTurnOffProfilingHook(TR::CompilationInfo * compInfo)3961{3962if (!compInfo->getPersistentInfo()->isClassLoadingPhase())3963{3964if (interpreterProfilingState == IPROFILING_STATE_ON)3965{3966interpreterProfilingRecordsCount = 0;3967interpreterProfilingState = IPROFILING_STATE_GOING_OFF;3968}3969}3970else if ((interpreterProfilingState == IPROFILING_STATE_GOING_OFF) ||3971(interpreterProfilingState == IPROFILING_STATE_OFF))3972{3973interpreterProfilingState = IPROFILING_STATE_ON;3974}39753976return false;3977}3978397939803981static void jitHookBytecodeProfiling(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData)3982{3983J9VMProfilingBytecodeBufferFullEvent* event = (J9VMProfilingBytecodeBufferFullEvent*)eventData;3984J9VMThread * vmThread = event->currentThread;3985const U_8* cursor = event->bufferStart;3986UDATA size = event->bufferSize;3987UDATA records = 0;3988TR_J9VMBase * fe = NULL;39893990PORT_ACCESS_FROM_VMC(vmThread);39913992if (TEST_verbose)3993{3994j9tty_printf(PORTLIB, "%p - Buffer full: %zu bytes at %p\n", vmThread, size, cursor);3995}3996//TEST_events += 1;39973998J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;3999if (jitConfig)4000fe = TR_J9VMBase::get(jitConfig, vmThread);4001else4002return;4003TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);4004// In DEEP_IDLE we seem to be interrupted too often by IProfiler buffers4005// sent by VM. To alleviate this issue the sampling thread will get out4006// of DEEP_IDLE only if the VM sends us buffers "very frequently".4007// Basically we measure the time needed for the arrival of several such4008// buffers and interrupt the sleep of the sampling thread if this time4009// is less than 5 seconds (configurable)4010if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)4011{4012static const uint32_t ARRAY_SIZE = 4; // must be power of two due to wrap around logic4013static uint64_t _IPBufferArrivalTimes[ARRAY_SIZE] = { 0 };4014static uint32_t crtPos = 0;40154016if (compInfo->getIProfilerBufferArrivalMonitor()) // safety check; will most likely exist4017{4018PORT_ACCESS_FROM_JITCONFIG(jitConfig);4019uint64_t crtTime = j9time_current_time_millis();40204021compInfo->getIProfilerBufferArrivalMonitor()->enter();40224023uint32_t oldestPos = (crtPos + 1) & (ARRAY_SIZE - 1);4024uint64_t oldestTime = _IPBufferArrivalTimes[oldestPos]; // read the oldest entry4025crtPos = oldestPos; // update position in the circular buffer4026_IPBufferArrivalTimes[oldestPos] = crtTime; // write the new entry40274028compInfo->getIProfilerBufferArrivalMonitor()->exit();40294030// Get out of deepIdle only if ARRAY_SIZE buffers arrive within 5 seconds4031// Note that crtTime can go backwards, however, this means we will get4032// out of deep idle more often that we should for a small period of time4033// (until we fill the entire array with new values)4034if ((oldestTime != 0) && (crtTime < oldestTime + TR::Options::_iProfilerBufferInterarrivalTimeToExitDeepIdle))4035{4036getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "IP buffer received"); // this changes the state to IDLE4037// TODO: try to induce compilations for methods on the Java stack4038}4039else4040{4041if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))4042{4043uint32_t t = (uint32_t)(crtTime - compInfo->getPersistentInfo()->getStartTime());4044TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread avoided an interruption in DEEP_IDLE due to IProfiler buffer being received", t);4045}4046}4047}4048}4049TR_ASSERT(fe, "FrontEnd must exist\n");4050TR_IProfiler *iProfiler = fe->getIProfiler();4051if (!iProfiler || !iProfiler->isIProfilingEnabled())4052{4053// Even if Iprofiler has been turned-off/stopped/disabled we should clear4054// the iprofiler buffer the VM has given us to avoid livelock (RTC 61279)4055vmThread->profilingBufferCursor = (U_8*)cursor; // discard the content4056return;4057}4058iProfiler->incrementNumRequests();4059if (TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))4060{4061iProfiler->parseBuffer(vmThread, cursor, size);4062vmThread->profilingBufferCursor = (U_8*)cursor; // reuse the same buffer4063}4064else // use a separate thread for iprofiler4065{4066if (!iProfiler->processProfilingBuffer(vmThread, cursor, size))4067{4068// iprofilerThread did not process or discard the buffer,4069// but it delegated this task to the java thread itself4070iProfiler->parseBuffer(vmThread, cursor, size);4071vmThread->profilingBufferCursor = (U_8*)cursor; // reuse the same buffer4072}4073}40744075checkAndTurnOffProfilingHook(compInfo);4076if (iProfiler->getProfilerMemoryFootprint() >= TR::Options::_iProfilerMemoryConsumptionLimit)4077{4078if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))4079{4080TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler exceeded memory limit %d", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), iProfiler->getProfilerMemoryFootprint());4081}4082turnOffInterpreterProfiling(jitConfig);4083// Generate a trace point4084Trc_JIT_IProfilerCapReached(vmThread, (iProfiler->getProfilerMemoryFootprint() >> 10));4085}40864087if (interpreterProfilingState == IPROFILING_STATE_GOING_OFF)4088{4089//interpreterProfilingRecordsCount += records;4090// interpreterProfilingRecordsCount could be artificially set very high from other parts of the code40914092if (interpreterProfilingRecordsCount >= TR::Options::_iprofilerSamplesBeforeTurningOff )4093{4094(*hook)->J9HookUnregister(hook, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, NULL);4095if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))4096{4097TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler stopped after %d records", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), TEST_records+records);4098}4099interpreterProfilingState = IPROFILING_STATE_OFF;4100}4101}4102}41034104#endif /* J9VM_INTERP_PROFILING_BYTECODES */41054106extern IDATA compileClasses(J9VMThread *, const char * pattern);41074108static void jitHookAboutToRunMain(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData)4109{4110J9VMLookupJNIIDEvent * event = (J9VMLookupJNIIDEvent *)eventData;4111J9VMThread * vmThread = event->currentThread;4112J9JavaVM * javaVM = vmThread->javaVM;4113J9JITConfig * jitConfig = javaVM->jitConfig;4114if (jitConfig == 0)4115return; // if a hook gets called after freeJitConfig then not much else we can do41164117if (!event->isStatic || event->isField || strncmp(event->name, "main", 4) || strncmp(event->signature, "([Ljava/lang/String;)V", 22))4118return;41194120J9HookInterface * * vmHooks = vmThread->javaVM->internalVMFunctions->getVMHookInterface(vmThread->javaVM);4121(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_LOOKUP_JNI_ID, jitHookAboutToRunMain, NULL);41224123bool alreadyHaveVMAccess = ((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) != 0);4124if (!alreadyHaveVMAccess)4125javaVM->internalVMFunctions->internalAcquireVMAccess(vmThread);4126javaVM->internalVMFunctions->acquireExclusiveVMAccess(vmThread);4127jitConfig->runtimeFlags &= ~J9JIT_DEFER_JIT;41284129#ifdef J9VM_JIT_SUPPORTS_DIRECT_JNI4130initializeDirectJNI(javaVM);4131#endif41324133jitResetAllMethodsAtStartup(vmThread);4134javaVM->internalVMFunctions->releaseExclusiveVMAccess(vmThread);4135if (!alreadyHaveVMAccess)4136javaVM->internalVMFunctions->internalReleaseVMAccess(vmThread);41374138if (TR::Options::getCmdLineOptions()->getOption(TR_jitAllAtMain))4139compileClasses(vmThread, "");4140}414141424143#if defined(J9VM_INTERP_PROFILING_BYTECODES)4144// Below, options and jitConfig are guaranteed to be not null4145void printIprofilerStats(TR::Options *options, J9JITConfig * jitConfig, TR_IProfiler *iProfiler)4146{4147if (!options->getOption(TR_DisableInterpreterProfiling))4148{4149PORT_ACCESS_FROM_JITCONFIG(jitConfig);4150if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))4151{4152j9tty_printf(PORTLIB, "VM shutdown event received.\n");4153j9tty_printf(PORTLIB, "Total events: %d\n", TEST_events);4154j9tty_printf(PORTLIB, "Total records: %d\n", TEST_records);4155j9tty_printf(PORTLIB, "Total method persistence opportunities: %d\n", TR_IProfiler::_STATS_methodPersistenceAttempts);4156j9tty_printf(PORTLIB, "Total jitprofile entries: %d\n", TR_IProfiler::_STATS_methodPersisted);4157j9tty_printf(PORTLIB, "Total IProfiler persistence aborted due to locked entry: %d\n", TR_IProfiler::_STATS_abortedPersistence);4158j9tty_printf(PORTLIB, "Total IProfiler persistence failed: %d\n", TR_IProfiler::_STATS_persistError);4159j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because SCC full: %d\n", TR_IProfiler::_STATS_methodNotPersisted_SCCfull);4160j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because ROM class in not in SCC: %d\n", TR_IProfiler::_STATS_methodNotPersisted_classNotInSCC);4161j9tty_printf(PORTLIB, "Total IProfiler persistence aborted due to other reasons: %d\n", TR_IProfiler::_STATS_methodNotPersisted_other);4162j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because already stored: %d\n", TR_IProfiler::_STATS_methodNotPersisted_alreadyStored);4163j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because nothing needs to be stored: %d\n", TR_IProfiler::_STATS_methodNotPersisted_noEntries);4164j9tty_printf(PORTLIB, "Total IProfiler persisted delayed: %d\n", TR_IProfiler::_STATS_methodNotPersisted_delayed);4165j9tty_printf(PORTLIB, "Total records persisted: %d\n", TR_IProfiler::_STATS_entriesPersisted);4166j9tty_printf(PORTLIB, "Total records not persisted_NotInSCC: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_NotInSCC);4167j9tty_printf(PORTLIB, "Total records not persisted_unloaded: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_Unloaded);4168j9tty_printf(PORTLIB, "Total records not persisted_noInfo in bc table: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_NoInfo);4169j9tty_printf(PORTLIB, "Total records not persisted_Other: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_Other);4170j9tty_printf(PORTLIB, "IP Total Persistent Read Failed Attempts: %d\n", TR_IProfiler::_STATS_persistedIPReadFail);41714172j9tty_printf(PORTLIB, "IP Total Persistent Reads with Bad Data: %d\n", TR_IProfiler::_STATS_persistedIPReadHadBadData);4173j9tty_printf(PORTLIB, "IP Total Persistent Read Success: %d\n", TR_IProfiler::_STATS_persistedIPReadSuccess);4174j9tty_printf(PORTLIB, "IP Total Persistent vs Current Data Differ: %d\n", TR_IProfiler::_STATS_persistedAndCurrentIPDataDiffer);4175j9tty_printf(PORTLIB, "IP Total Persistent vs Current Data Match: %d\n", TR_IProfiler::_STATS_persistedAndCurrentIPDataMatch);4176j9tty_printf(PORTLIB, "IP Total Current Read Fail: %d\n", TR_IProfiler::_STATS_currentIPReadFail);4177j9tty_printf(PORTLIB, "IP Total Current Read Success: %d\n", TR_IProfiler::_STATS_currentIPReadSuccess);4178j9tty_printf(PORTLIB, "IP Total Current Read Bad Data: %d\n", TR_IProfiler::_STATS_currentIPReadHadBadData);4179j9tty_printf(PORTLIB, "Total records read: %d\n", TR_IProfiler::_STATS_IPEntryRead);4180j9tty_printf(PORTLIB, "Total records choose persistent: %d\n", TR_IProfiler::_STATS_IPEntryChoosePersistent);4181}4182if (TR_IProfiler::_STATS_abortedPersistence > 0)4183{4184TR_ASSERT(TR_IProfiler::_STATS_methodPersisted / TR_IProfiler::_STATS_abortedPersistence > 20 ||4185TR_IProfiler::_STATS_methodPersisted < 200,4186"too many aborted persistence attempts due to locked entries (%d aborted, %d total methods persisted)",4187TR_IProfiler::_STATS_abortedPersistence, TR_IProfiler::_STATS_methodPersisted);4188}4189if (TR::Options::getCmdLineOptions()->getOption(TR_EnableNewAllocationProfiling))4190iProfiler->printAllocationReport();4191if (TEST_verbose || TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))4192iProfiler->outputStats();4193}4194}4195#endif419641974198/// JIT cleanup code4199void JitShutdown(J9JITConfig * jitConfig)4200{4201static bool jitShutdownCalled = false;42024203if (!jitConfig)4204return; // there isn't much we can do without a jitConfig42054206J9JavaVM * javaVM = jitConfig->javaVM;4207J9VMThread *vmThread = javaVM->internalVMFunctions->currentVMThread(javaVM);42084209// Prevent calling this function twice;4210// Races cannot occur because only the main thread executes shutdown stages4211if (jitShutdownCalled)4212{4213TRC_JIT_ShutDownEnd(vmThread, "jitShutdownCalled is true");4214return;4215}4216jitShutdownCalled = true;42174218TRC_JIT_ShutDownBegin(vmThread);42194220TR_J9VMBase * vm = TR_J9VMBase::get(jitConfig, NULL);4221// The rest of this function seems to only be valid if we have managed to allocate at least the global VM.4222if (!vm)4223{4224TRC_JIT_ShutDownEnd(vmThread, "vm variable is NULL");4225return;4226}422742284229PORT_ACCESS_FROM_JAVAVM(javaVM);42304231TR::Options *options = TR::Options::getCmdLineOptions();4232#if defined(J9VM_INTERP_PROFILING_BYTECODES)4233TR_ASSERT(jitConfig->privateConfig, "privateConfig must exist if a frontend exists\n");4234TR_IProfiler *iProfiler = vm->getIProfiler();42354236// The TR_DisableInterpreterProfiling options can change during run4237// so the fact that this option is true doesn't mean that IProfiler structures were not allocated4238if (options /* && !options->getOption(TR_DisableInterpreterProfiling) */ && iProfiler)4239{4240printIprofilerStats(options, jitConfig, iProfiler);4241// Prevent the interpreter to accumulate more info4242// stopInterpreterProfiling is stronger than turnOff... because it prevents the reactivation4243// by setting TR_DisableInterpreterProfiling option to false4244stopInterpreterProfiling(jitConfig);4245if (!options->getOption(TR_DisableIProfilerThread))4246iProfiler->stopIProfilerThread();4247#ifdef DEBUG4248uint32_t lockedEntries = iProfiler->releaseAllEntries();4249TR_ASSERT(lockedEntries == 0, "some entries were still locked on shutdown");4250#endif4251// Dump all IProfiler related to virtual/interface invokes and instanceof/checkcasts4252// to track possible performance issues4253// iProfiler->dumpIPBCDataCallGraph(vmThread);42544255// free the IProfiler structures42564257// Deallocate the buffers used for interpreter profiling4258// Must be called when we are sure that no java thread can be running4259// Or at least that Java threads do not try to collect IProfiler info4260// We turn off IProfiler above, but let's add another check4261if (interpreterProfilingState == IPROFILING_STATE_OFF)4262iProfiler->deallocateIProfilerBuffers();4263iProfiler->shutdown();4264}4265#endif // J9VM_INTERP_PROFILING_BYTECODES42664267TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);42684269TR_HWProfiler *hwProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->hwProfiler;4270if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())4271{4272char * printRIStats = feGetEnv("TR_PrintRIStats");4273if (printRIStats)4274hwProfiler->printStats();42754276if (!options->getOption(TR_DisableHWProfilerThread))4277{4278hwProfiler->stopHWProfilerThread(javaVM);4279hwProfiler->releaseAllEntries();4280}4281}42824283// Hardware profiling4284#ifdef J9VM_JIT_RUNTIME_INSTRUMENTATION4285if (NULL != hwProfiler)4286shutdownJITRuntimeInstrumentation(javaVM);4287#endif42884289TR_JProfilerThread *jProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->jProfiler;4290if (jProfiler != NULL)4291jProfiler->stop(javaVM);42924293if (options && options->getOption(TR_DumpFinalMethodNamesAndCounts))4294{4295try4296{4297TR::RawAllocator rawAllocator(jitConfig->javaVM);4298J9::SegmentAllocator segmentAllocator(MEMORY_TYPE_JIT_SCRATCH_SPACE | MEMORY_TYPE_VIRTUAL, *jitConfig->javaVM);4299J9::SystemSegmentProvider regionSegmentProvider(43001 << 20,43011 << 20,4302TR::Options::getScratchSpaceLimit(),4303segmentAllocator,4304rawAllocator4305);4306TR::Region dispatchRegion(regionSegmentProvider, rawAllocator);4307TR_Memory trMemory(*compInfo->persistentMemory(), dispatchRegion);43084309compInfo->getPersistentInfo()->getPersistentCHTable()->dumpMethodCounts(vm, trMemory);4310}4311catch (const std::exception &e)4312{4313fprintf(stderr, "Failed to dump Final Method Names and Counts\n");4314}4315}43164317TR::Compilation::shutdown(vm);43184319TR::CompilationController::shutdown();43204321if (!vm->isAOT_DEPRECATED_DO_NOT_USE())4322stopSamplingThread(jitConfig);43234324#if defined(J9VM_OPT_JITSERVER)4325JITServerStatisticsThread *statsThreadObj = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->statisticsThreadObject;4326if (statsThreadObj)4327{4328statsThreadObj->stopStatisticsThread(jitConfig);4329}4330#endif43314332TR_DebuggingCounters::report();4333accumulateAndPrintDebugCounters(jitConfig);43344335// TODO:JSR292: Delete or protect with env var4336/*4337TR_FrontEnd *fe = TR_J9VMBase::get(jitConfig, vmThread);4338TR_J2IThunkTable *thunkTable = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getInvokeExactJ2IThunkTable();4339if (thunkTable)4340thunkTable->dumpTo(fe, TR::IO::Stdout);4341*/43424343if (options && options->getOption(TR_VerboseInlineProfiling))4344{4345j9tty_printf(PORTLIB, "Inlining statistics:\n");4346j9tty_printf(PORTLIB, "\tFailed to devirtualize virtual calls: %10d\n", TR::Options::INLINE_failedToDevirtualize);4347j9tty_printf(PORTLIB, "\tFailed to devirtualize interface calls: %10d\n", TR::Options::INLINE_failedToDevirtualizeInterface);4348j9tty_printf(PORTLIB, "\tCallee method is too big: %10d\n", TR::Options::INLINE_calleeToBig);4349j9tty_printf(PORTLIB, "\tCallee method is too deep: %10d\n", TR::Options::INLINE_calleeToDeep);4350j9tty_printf(PORTLIB, "\tCallee method has too many nodes: %10d\n", TR::Options::INLINE_calleeHasTooManyNodes);4351j9tty_printf(PORTLIB, "\tRan out of inlining budget: %10d\n\n", TR::Options::INLINE_ranOutOfBudget);43524353if (TR::Options::INLINE_calleeToBig)4354j9tty_printf(PORTLIB, "\tCallee method is too big (avg): %10d\n", TR::Options::INLINE_calleeToBigSum / TR::Options::INLINE_calleeToBig);4355else4356j9tty_printf(PORTLIB, "\tCallee method is too big (avg): x\n");4357if (TR::Options::INLINE_calleeToDeep)4358j9tty_printf(PORTLIB, "\tCallee method is too deep (avg): %10d\n", TR::Options::INLINE_calleeToDeepSum / TR::Options::INLINE_calleeToDeep);4359else4360j9tty_printf(PORTLIB, "\tCallee method is too deep (avg): x\n");43614362if (TR::Options::INLINE_calleeHasTooManyNodes)4363j9tty_printf(PORTLIB, "\tCallee method has too many nodes (avg): %10d\n", TR::Options::INLINE_calleeHasTooManyNodesSum / TR::Options::INLINE_calleeHasTooManyNodes);4364else4365j9tty_printf(PORTLIB, "\tCallee method has too many nodes (avg): x\n");43664367j9tty_printf(PORTLIB, "\tHas no profiling info: %10d\n", TR_IProfiler::_STATS_noProfilingInfo);4368j9tty_printf(PORTLIB, "\tHas weak profiling info: %10d\n", TR_IProfiler::_STATS_weakProfilingRatio);4369j9tty_printf(PORTLIB, "\tDoesn't want to give profiling info: %10d\n", TR_IProfiler::_STATS_doesNotWantToGiveProfilingInfo);4370j9tty_printf(PORTLIB, "\tNo prof. info cause cannot get classInfo:%10d\n", TR_IProfiler::_STATS_cannotGetClassInfo);4371j9tty_printf(PORTLIB, "\tNo prof. info because timestamp expired: %10d\n", TR_IProfiler::_STATS_timestampHasExpired);4372}43734374#if defined(J9VM_OPT_JITSERVER)4375static char * isPrintJITServerMsgStats = feGetEnv("TR_PrintJITServerMsgStats");4376if (isPrintJITServerMsgStats)4377JITServerHelpers::printJITServerMsgStats(jitConfig, compInfo);4378static char * isPrintJITServerCHTableStats = feGetEnv("TR_PrintJITServerCHTableStats");4379if (isPrintJITServerCHTableStats)4380JITServerHelpers::printJITServerCHTableStats(jitConfig, compInfo);4381#endif43824383TRC_JIT_ShutDownEnd(vmThread, "end of JitShutdown function");4384}43854386static void samplingObservationsLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo)4387{4388if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHeartbeat))4389{4390TR_VerboseLog::CriticalSection vlogLock;4391TR_VerboseLog::writeLine(TR_Vlog_INFO,"<samplewindow intervalTicks=%u interpretedMethodSamples=%u",4392jitConfig->samplingTickCount + 1 - compInfo->_stats._windowStartTick, compInfo->_stats._interpretedMethodSamples);4393TR_VerboseLog::writeLine(TR_Vlog_INFO," compiledMethodSamples=%u compiledMethodSamplesIgnored=%u",4394compInfo->_stats._compiledMethodSamples, compInfo->_stats._compiledMethodSamplesIgnored);4395TR_VerboseLog::writeLine(TR_Vlog_INFO," samplesSent=%u samplesReceived=%u ticksInIdleMode=%u",4396compInfo->_stats._sampleMessagesSent, compInfo->_stats._sampleMessagesReceived, compInfo->_stats._ticksInIdleMode);4397TR_VerboseLog::writeLine(TR_Vlog_INFO," methodsCompiledOnCount=%u methodsReachingSampleInterval=%u",4398compInfo->_stats._methodsCompiledOnCount, compInfo->_stats._methodsReachingSampleInterval);4399}44004401// sample tick is about to be incremented for the samples we're about to take4402compInfo->_stats._windowStartTick = jitConfig->samplingTickCount + 1;4403compInfo->_stats._sampleMessagesSent = 0;4404compInfo->_stats._sampleMessagesReceived = 0;4405compInfo->_stats._ticksInIdleMode = 0;4406compInfo->_stats._interpretedMethodSamples = 0;4407compInfo->_stats._compiledMethodSamples = 0;4408compInfo->_stats._compiledMethodSamplesIgnored = 0;4409compInfo->_stats._methodsCompiledOnCount=0;4410compInfo->_stats._methodsReachingSampleInterval = 0;4411compInfo->_stats._methodsSelectedToRecompile = 0;4412compInfo->_stats._methodsSampleWindowReset = 0;4413}44144415char* jitStateNames[]=4416{4417"UNDEFINED",4418"IDLE ",4419"STARTUP ",4420"RAMPUP ",4421"STEADY ",4422"DEEPSTEADY",4423};44244425static int32_t startupPhaseId = 0;4426static bool firstIdleStateAfterStartup = false;4427static uint64_t timeToAllocateTrackingHT = 0xffffffffffffffff; // never44284429#define GCR_HYSTERESIS 10044304431static void jitStateLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo, uint32_t diffTime)4432{4433// We enter STARTUP too often because IDLE is not operating correctly4434static uint64_t lastTimeInJITStartupMode = 0;4435TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();4436uint64_t crtElapsedTime = persistentInfo->getElapsedTime();44374438static int32_t rampupPhaseID = 0;4439static uint32_t oldNumClassesLoaded = 0;4440J9JavaVM * javaVM = jitConfig->javaVM;44414442uint32_t numClassesLoadedInInterval = (uint32_t)persistentInfo->getNumLoadedClasses() - oldNumClassesLoaded;4443uint32_t numClassesLoadedInIntervalNormalized = numClassesLoadedInInterval*1000/diffTime;4444oldNumClassesLoaded = (uint32_t)persistentInfo->getNumLoadedClasses(); // remember for next time44454446uint8_t oldState = persistentInfo->getJitState();4447uint8_t newState;4448uint32_t totalSamples = compInfo->_intervalStats._compiledMethodSamples + compInfo->_intervalStats._interpretedMethodSamples;4449uint32_t totalSamplesNormalized = totalSamples*1000/diffTime;4450uint32_t samplesSentNormalized = compInfo->_intervalStats._samplesSentInInterval*1000/diffTime;4451float iSamplesRatio = totalSamples ? compInfo->_intervalStats._interpretedMethodSamples/(float)totalSamples : 0;4452uint32_t totalCompilationsNormalized = (compInfo->_intervalStats._numRecompilationsInInterval + compInfo->_intervalStats._numFirstTimeCompilationsInInterval)*1000/diffTime;44534454// Read the CPU utilization as a percentage; -1 if not functional;4455// Can be greater than 100% if multiple cores4456static int32_t oldJvmCpuUtil = 10;4457int32_t avgJvmCpuUtil;4458if (compInfo->getCpuUtil()->isFunctional())4459{4460int32_t jvmCpuUtil = compInfo->getCpuUtil()->getVmCpuUsage();4461avgJvmCpuUtil = (oldJvmCpuUtil + jvmCpuUtil) >> 1;4462oldJvmCpuUtil = jvmCpuUtil;4463}4464else4465{4466avgJvmCpuUtil = -1;4467}44684469if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_IDLE || // No need to acquire the monitor to read these4470compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE ||4471(avgJvmCpuUtil >= 0 && avgJvmCpuUtil <= 2) || // 2% or less CPU utilization puts us in idle mode4472(!persistentInfo->isClassLoadingPhase() && // classLoadPhase put us in STARTUP state4473totalCompilationsNormalized < 10 && // if compilations are taking place we cannot be in IDLE mode4474avgJvmCpuUtil < 10 && // if the JVM is using 10% or more CPU it cannot be idle4475compInfo->getMethodQueueSize() < TR::CompilationInfo::LARGE_QUEUE && // we cannot be in IDLE mode if the queue is large4476((totalSamplesNormalized < 6 && samplesSentNormalized < 6) || // very few samples puts us in IDLE mode4477(oldState == IDLE_STATE && totalSamplesNormalized <= 15) || // while in IDLE mode the number of samples criterion becomes more lax4478(oldState != STARTUP_STATE && totalSamplesNormalized <=22 && iSamplesRatio > 0.5)4479)4480)4481)4482{4483newState = IDLE_STATE;4484}4485else if (persistentInfo->isClassLoadingPhase()) // new classe being injected into the system4486{4487newState = STARTUP_STATE;4488if (oldState != STARTUP_STATE)4489startupPhaseId++;4490lastTimeInJITStartupMode = crtElapsedTime;4491}4492// Make it easier to stay in STARTUP if we are already in startup, but harder otherwise4493else if ((oldState == STARTUP_STATE &&4494compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime < 30 && // many recompilations puts us in RAMPUP4495((compInfo->_intervalStats._compiledMethodSamples == 0) ||4496(iSamplesRatio > 0.25) || // we could go for 0.33 when there are many samples4497(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 200) // 200 new compilations per second4498)4499) ||4500(oldState != STARTUP_STATE && // to come back to STARTUP we need at least one class to be loaded4501(numClassesLoadedInIntervalNormalized > 0) &&4502((compInfo->_intervalStats._compiledMethodSamples == 0) ||4503// If many interpreter samples then go to STARTUP, but only if we have enough overall samples to decide4504((iSamplesRatio > 0.5) && (oldState != IDLE_STATE && totalSamplesNormalized > 15)) ||4505(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 250 &&4506compInfo->_intervalStats._numRecompilationsInInterval < 3)4507)4508)4509)4510// first-time-compilations/sec > threshold ==> must take into account machine speed; counts also affect this4511{4512newState = STARTUP_STATE;4513if (oldState != STARTUP_STATE)4514startupPhaseId++;4515lastTimeInJITStartupMode = crtElapsedTime;4516}4517else if ((oldState == RAMPUP_STATE &&4518((compInfo->getMethodQueueSize() > TR::CompilationInfo::SMALL_QUEUE) ||4519(compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime >= 1) ||4520(compInfo->_intervalStats._numRecompPrevInterval*1000/diffTime >= 1) ||4521(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 15) ||4522//(compInfo->_intervalStats._interpretedMethodSamples*1000/diffTime > 10) // too many int samples ==> don't go to steady state yet4523(iSamplesRatio > 0.15) // not enough compiled samples to go to STEADY4524)4525) ||4526(oldState != RAMPUP_STATE &&4527((compInfo->getMethodQueueSize() >= TR::CompilationInfo::MEDIUM_LARGE_QUEUE) ||4528(compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime > 6) ||4529(oldState != STEADY_STATE && oldState != DEEPSTEADY_STATE && compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime > 2) ||4530(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 55) ||4531(oldState == STARTUP_STATE && rampupPhaseID == 0) // if we never had a rampup phase, switch now4532)4533)4534)4535// If the number of recompilations is not that high up to this point, do not hurry up to move from RAMPUP to STEADY4536// Maybe those recompilations will happen later4537{4538newState = RAMPUP_STATE;4539if (oldState != RAMPUP_STATE)4540rampupPhaseID++;4541}4542else // We will go to STEADY or DEEP_STEADY4543{4544if (oldState == DEEPSTEADY_STATE || // keep the DEEPSTEADY_STATE4545// after 10 minutes or STEADY_STATE switch to DEEPSTEADY_STATE4546// The 10 minutes may be shorter when multiple threads are running full speed4547// or longer when there isn't much work to be done4548((oldState == STEADY_STATE) && ((persistentInfo->getJitTotalSampleCount() - persistentInfo->getJitSampleCountWhenActiveStateEntered()) > 60000)))4549{4550newState = DEEPSTEADY_STATE;4551}4552else4553{4554newState = STEADY_STATE;4555}4556}4557// A surge in compilations can make the transition back to STARTUP4558//t= 98186 oldState=3 newState=2 cSamples=125 iSamples= 11 comp=239 recomp= 4, Q_SZ=11445594560static uint64_t lastTimeInStartupMode = 0;45614562// current JPQ implementation does not use this, but it may need to be re-animated shortly so leaving commented out for now4563/*static char *disableJProfilingRecomp = feGetEnv("TR_DisableJProfilingRecomp");4564const int32_t intervalBase = 17000;4565if (disableJProfilingRecomp == NULL4566&& javaVM->phase == J9VM_PHASE_NOT_STARTUP)4567{4568if (*(TR_BlockFrequencyInfo::getEnableJProfilingRecompilation()) == 0)4569{4570if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase)4571{4572TR_BlockFrequencyInfo::enableJProfilingRecompilation();4573if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerboseCompileEnd, TR_VerbosePerformance))4574{4575TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Enabling JProfiling recompilation. recompileThrehold = %d loopRecompileThreshold = %d nestedLoopRecompileThreshold = %d", TR_JProfiling::recompileThreshold, TR_JProfiling::loopRecompileThreshold, TR_JProfiling::nestedLoopRecompileThreshold);4576}4577}4578}4579else if (TR_JProfiling::recompileThreshold > 100)4580{4581bool thresholdsLowered = false;4582if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase + 30000)4583{4584TR_JProfiling::recompileThreshold = 100;4585TR_JProfiling::loopRecompileThreshold = 10;4586TR_JProfiling::nestedLoopRecompileThreshold = 1;4587thresholdsLowered = true;4588}4589else if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase + 20000)4590{4591TR_JProfiling::recompileThreshold = 10000;4592TR_JProfiling::loopRecompileThreshold = 1000;4593TR_JProfiling::nestedLoopRecompileThreshold = 100;4594thresholdsLowered = true;4595}4596else if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase + 10000)4597{4598TR_JProfiling::recompileThreshold = 100000;4599TR_JProfiling::loopRecompileThreshold = 10000;4600TR_JProfiling::nestedLoopRecompileThreshold = 1000;4601thresholdsLowered = true;4602}4603if (thresholdsLowered && TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerboseCompileEnd, TR_VerbosePerformance))4604{4605TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Lowering JProfiling recompilation thresholds. recompileThrehold = %d loopRecompileThreshold = %d nestedLoopRecompileThreshold = %d", TR_JProfiling::recompileThreshold, TR_JProfiling::loopRecompileThreshold, TR_JProfiling::nestedLoopRecompileThreshold);4606}4607}4608}*/4609/*if (disableJProfilingRecomp == NULL4610&& javaVM->phase == J9VM_PHASE_NOT_STARTUP4611&& (crtElapsedTime - lastTimeInJITStartupMode) > 80000 //&& crtElapsedTime > 1500004612&& *(TR_BlockFrequencyInfo::getEnableJProfilingRecompilation()) == 0)4613{4614printf("Enabling JProfiling recompilation\n");4615TR_BlockFrequencyInfo::enableJProfilingRecompilation();4616}*/461746184619// Enable/disable GCR counting4620if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations) &&4621!TR::Options::getJITCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations))4622{4623if (!persistentInfo->_countForRecompile)// if counting is not yet enabled4624{4625bool enable = false;4626if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods) ||4627TR::Options::getJITCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods))4628{4629if (newState != STARTUP_STATE && // Do not enable GCR counting during JIT startup4630javaVM->phase == J9VM_PHASE_NOT_STARTUP && // Do not enable GCR counting during VM startup4631newState != DEEPSTEADY_STATE && // Do not enable GCR counting during DEEPSTEADY4632crtElapsedTime - lastTimeInJITStartupMode > TR::Options::_waitTimeToGCR &&4633// Do not enable GCR counting if we already have a large number of queued GCR requests4634compInfo->getNumGCRRequestsQueued() <= TR::Options::_GCRQueuedThresholdForCounting-GCR_HYSTERESIS)4635enable = true;4636}4637else // Old scheme4638{4639if (crtElapsedTime - lastTimeInJITStartupMode > TR::Options::_waitTimeToGCR)4640enable = true;4641}4642if (enable)4643{4644persistentInfo->_countForRecompile = 1; // flip the bit4645// write a message in the vlog4646if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))4647TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u GCR enabled; GCR queued=%d", (uint32_t)crtElapsedTime, compInfo->getNumGCRRequestsQueued());4648}4649}4650else // GCR counting is already enabled; see if we need to disable it4651{4652if ((TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods) ||4653TR::Options::getJITCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods))4654&& // stop counting if STARTUP, DEEPSTEADY or too many queued GCR requests4655(newState == STARTUP_STATE ||4656newState == DEEPSTEADY_STATE ||4657compInfo->getNumGCRRequestsQueued() > TR::Options::_GCRQueuedThresholdForCounting+GCR_HYSTERESIS)4658)4659{4660persistentInfo->_countForRecompile = 0; // disable counting4661// write a message in the vlog4662if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))4663TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u GCR disabled; GCR queued=%d", (uint32_t)crtElapsedTime, compInfo->getNumGCRRequestsQueued());4664}4665}4666}46674668// Enable/Disable RI Buffer processing4669if (persistentInfo->isRuntimeInstrumentationEnabled())4670{4671TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();46724673if (TR::Options::_hwProfilerExpirationTime != 0 &&4674crtElapsedTime > TR::Options::_hwProfilerExpirationTime)4675{4676if (!hwProfiler->isExpired())4677{4678hwProfiler->setExpired();4679hwProfiler->setProcessBufferState(-1);4680if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler, TR_VerbosePerformance))4681TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Buffer processing is disabled because expiration time has been reached");4682}4683}4684else if (hwProfiler->getProcessBufferState() >= 0) // Buffer profiling is ON4685{4686// Should we turn it off?4687if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicRIBufferProcessing))4688{4689hwProfiler->checkAndTurnBufferProcessingOff();4690}4691else if (TR::Options::getCmdLineOptions()->getOption(TR_InhibitRIBufferProcessingDuringDeepSteady))4692{4693if (oldState != newState && newState == DEEPSTEADY_STATE)4694{4695hwProfiler->setProcessBufferState(-1);4696if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler, TR_VerbosePerformance))4697TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Buffer processing is disabled");4698}4699}4700}4701else // Should we turn it on?4702{4703if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicRIBufferProcessing))4704{4705// Do not turn on during startup4706if (javaVM->phase == J9VM_PHASE_NOT_STARTUP)4707hwProfiler->checkAndTurnBufferProcessingOn();4708}4709else if (TR::Options::getCmdLineOptions()->getOption(TR_InhibitRIBufferProcessingDuringDeepSteady))4710{4711if (oldState != newState && oldState == DEEPSTEADY_STATE)4712{4713hwProfiler->setProcessBufferState(TR::Options::_hwProfilerRIBufferProcessingFrequency);4714if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler, TR_VerbosePerformance))4715TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Buffer processing is enabled");4716}4717}4718}4719}47204721// Control how much application threads will be sleeping to give4722// application threads more time on the CPU4723TR_YesNoMaybe starvation = compInfo->detectCompThreadStarvation();4724bool newStarvationStatus = (starvation == TR_yes);4725if (newStarvationStatus != compInfo->getStarvationDetected()) // did the status change?4726{4727if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))4728TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Starvation status changed to %d QWeight=%d CompCPUUtil=%d CompThreadsActive=%d",4729(uint32_t)crtElapsedTime, starvation, compInfo->getOverallQueueWeight(),4730compInfo->getTotalCompThreadCpuUtilWhenStarvationComputed(),4731compInfo->getNumActiveCompThreadsWhenStarvationComputed());4732compInfo->setStarvationDetected(newStarvationStatus);4733}47344735if (TR::Options::getCmdLineOptions()->getOption(TR_EnableAppThreadYield))4736{4737int32_t oldSleepNano = compInfo->getAppSleepNano();4738int32_t newSleepNano = starvation != TR_yes ? 0 :compInfo->computeAppSleepNano(); // TODO should we look at JIT state as well4739if (newSleepNano != oldSleepNano)4740{4741compInfo->setAppSleepNano(newSleepNano);4742if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))4743TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u SleepTime changed from %d to %d QWeight=%d", (uint32_t)crtElapsedTime, oldSleepNano, newSleepNano, compInfo->getOverallQueueWeight());4744}4745}474647474748#if defined(J9VM_INTERP_PROFILING_BYTECODES)4749// Turn on Iprofiler if we started with it OFF and it has never been activated before4750//4751static bool IProfilerOffSinceStartup = true;47524753if (IProfilerOffSinceStartup &&4754!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling) &&4755TR::Options::getCmdLineOptions()->getOption(TR_NoIProfilerDuringStartupPhase) &&4756interpreterProfilingState == IPROFILING_STATE_OFF)4757{4758// Should we turn it ON?4759TR_IProfiler *iProfiler = TR_J9VMBase::get(jitConfig, 0)->getIProfiler();4760uint32_t failRate = iProfiler->getReadSampleFailureRate();4761if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitState))4762{4763TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler current fail rate = %u total=%u fail=%u samplesInBuffer=%u",4764(uint32_t)crtElapsedTime, failRate, iProfiler->getTotalReadSampleRequests(),4765iProfiler->getFailedReadSampleRequests(), iProfiler->numSamplesInHistoryBuffer());4766}4767if (crtElapsedTime - lastTimeInJITStartupMode > TR::Options::_waitTimeToStartIProfiler ||4768(int32_t)failRate > TR::Options::_iprofilerFailRateThreshold)4769{4770interpreterProfilingMonitoringWindow = 0;4771IProfilerOffSinceStartup = false;4772turnOnInterpreterProfiling(jitConfig->javaVM, compInfo);4773if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))4774{4775TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler enabled", (uint32_t)crtElapsedTime);4776}4777}4778iProfiler->advanceEpochForHistoryBuffer();4779}4780#endif // defined(J9VM_INTERP_PROFILING_BYTECODES)47814782if (TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&4783TR::Options::getCmdLineOptions()->getOption(TR_EarlyLPQ))4784{4785if (!compInfo->getLowPriorityCompQueue().isTrackingEnabled() && timeToAllocateTrackingHT == 0xffffffffffffffff)4786{4787uint64_t t = crtElapsedTime + TR::Options::_delayToEnableIdleCpuExploitation;4788if (TR::Options::_compilationDelayTime > 0 && (uint64_t)TR::Options::_compilationDelayTime > t)4789t = TR::Options::_compilationDelayTime;4790timeToAllocateTrackingHT = t;4791}4792}47934794// We should accelerate compilations of methods that get samples during rampup or steady state4795// The invocation count is decremented too slow4796// Set the state in the VM4797if (javaVM->phase != J9VM_PHASE_NOT_STARTUP) // once in NOT_STARTUP we cannot perform any changes4798{4799if (javaVM->phase == J9VM_PHASE_STARTUP)4800{4801// Analyze if we exited the STARTUP stage4802// Tolerate situations when we temporarily go out from STARTUP4803// Use JIT heuristics if (1) 'beginningOfStartup' hint didn't arrive yet OR4804// (2) Both 'beginningOfStartup' and 'endOfStartup' hints arrived,4805// but we don't follow hints strictly outside startup4806if (!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo) ||4807(persistentInfo->getExternalStartupEndedSignal() && !TR::Options::getCmdLineOptions()->getOption(TR_UseStrictStartupHints)))4808{4809//if (newState != STARTUP_STATE && oldState != STARTUP_STATE)4810// javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);4811if (newState != STARTUP_STATE)4812{4813int32_t waitTime = TR::Options::_waitTimeToExitStartupMode;4814// Double this value for zOS control region4815#if defined(J9ZOS390)4816if (compInfo->isInZOSSupervisorState())4817waitTime = waitTime * 2;4818#endif4819if (crtElapsedTime - lastTimeInStartupMode > waitTime)4820{4821javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);4822}4823}4824else4825{4826lastTimeInStartupMode = crtElapsedTime;4827}4828}4829else // The application will provide hints about startup ending4830{4831// Exit startup when the 'endOfStartup' arrives4832// The case where the 'endOfStartup' hint arrived, but don't want to follow strictly4833// is implemented above in the IF block4834if (persistentInfo->getExternalStartupEndedSignal())4835javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);4836}4837}4838else // javaVM->phase == J9VM_PHASE_EARLY_STARTUP4839{4840//TR_ASSERT(!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo), "assertion failure"); // we should be in STARTUP4841// Use JIT heuristics if (1) 'beginningOfStartup' hint didn't arrive yet OR4842// (2) Both 'beginningOfStartup' and 'endOfStartup' hints arrived,4843// but we don't follow hints strictly outside startup4844if (!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo) ||4845(persistentInfo->getExternalStartupEndedSignal() && !TR::Options::getCmdLineOptions()->getOption(TR_UseStrictStartupHints)))4846{4847// Normal gracePeriod rules apply4848if (crtElapsedTime >= (uint64_t)persistentInfo->getClassLoadingPhaseGracePeriod()) // grace period has ended4849javaVM->internalVMFunctions->jvmPhaseChange(javaVM, (newState == STARTUP_STATE) ? J9VM_PHASE_STARTUP : J9VM_PHASE_NOT_STARTUP);4850}4851else4852{4853// 'beginningOfStartup' hint was seen4854// If 'endOfStartup' was not seen, move to STARTUP, otherwise, following hints strictly,4855// we have to exit STARTUP4856javaVM->internalVMFunctions->jvmPhaseChange(javaVM, !persistentInfo->getExternalStartupEndedSignal() ? J9VM_PHASE_STARTUP : J9VM_PHASE_NOT_STARTUP);4857}4858}4859if (javaVM->phase == J9VM_PHASE_NOT_STARTUP)4860{4861// We just exited the STARTUP phase4862// Print a message in the vlog4863if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerboseCompileEnd, TR_VerbosePerformance))4864{4865TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u VM changed state to NOT_STARTUP", (uint32_t)crtElapsedTime);4866}4867// Release AOT data caches to normal compilations4868TR_DataCacheManager::getManager()->startupOver();48694870// Logic related to IdleCPU exploitation4871// If we are in idle mode immediately after JVM exited startup mode, set specific flag4872if (newState == IDLE_STATE)4873{4874firstIdleStateAfterStartup = true;4875}4876// If we don't hit idle state when we exit JVM startup, set the desired timestamp to allocate the tracking hashtable4877else if (TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&4878!compInfo->getLowPriorityCompQueue().isTrackingEnabled())4879{4880uint64_t t = crtElapsedTime + TR::Options::_delayToEnableIdleCpuExploitation;4881if (TR::Options::_compilationDelayTime > 0 && (uint64_t)TR::Options::_compilationDelayTime > t)4882t = TR::Options::_compilationDelayTime;4883timeToAllocateTrackingHT = t;4884}48854886// If we wanted to restrict inliner during startup, now it's the time to let the inliner go4887// Note: if we want to extend the heuristic of when Inliner should be restricted4888// we have to change the condition below4889if ((TR::Options::getCmdLineOptions()->getOption(TR_RestrictInlinerDuringStartup) ||4890TR::Options::getAOTCmdLineOptions()->getOption(TR_RestrictInlinerDuringStartup)) &&4891persistentInfo->getInlinerTemporarilyRestricted())4892{4893persistentInfo->setInlinerTemporarilyRestricted(false);4894if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))4895{4896TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u Stopped restricting the inliner", (uint32_t)crtElapsedTime);4897}4898}489949004901// If using lower counts, start using higher counts4902if (TR::Options::getCmdLineOptions()->getOption(TR_UseHigherMethodCountsAfterStartup) &&4903TR::Options::sharedClassCache())4904{4905if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))4906{4907TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u JIT counts: %d %d %d AOT counts: %d %d %d",4908(uint32_t)crtElapsedTime,4909TR::Options::getCmdLineOptions()->getInitialCount(),4910TR::Options::getCmdLineOptions()->getInitialBCount(),4911TR::Options::getCmdLineOptions()->getInitialMILCount(),4912TR::Options::getAOTCmdLineOptions()->getInitialCount(),4913TR::Options::getAOTCmdLineOptions()->getInitialBCount(),4914TR::Options::getAOTCmdLineOptions()->getInitialMILCount());4915}4916TR::Options::getCmdLineOptions()->setInitialCount(TR_DEFAULT_INITIAL_COUNT);4917TR::Options::getCmdLineOptions()->setInitialBCount(TR_DEFAULT_INITIAL_BCOUNT);4918TR::Options::getCmdLineOptions()->setInitialMILCount(TR_DEFAULT_INITIAL_MILCOUNT);4919TR::Options::getAOTCmdLineOptions()->setInitialCount(TR_DEFAULT_INITIAL_COUNT);4920TR::Options::getAOTCmdLineOptions()->setInitialBCount(TR_DEFAULT_INITIAL_BCOUNT);4921TR::Options::getAOTCmdLineOptions()->setInitialMILCount(TR_DEFAULT_INITIAL_MILCOUNT);49224923if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))4924{4925TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u JIT changed invocation counts to: JIT: %d %d %d AOT: %d %d %d",4926(uint32_t)crtElapsedTime,4927TR::Options::getCmdLineOptions()->getInitialCount(),4928TR::Options::getCmdLineOptions()->getInitialBCount(),4929TR::Options::getCmdLineOptions()->getInitialMILCount(),4930TR::Options::getAOTCmdLineOptions()->getInitialCount(),4931TR::Options::getAOTCmdLineOptions()->getInitialBCount(),4932TR::Options::getAOTCmdLineOptions()->getInitialMILCount());4933}4934}4935} // if (javaVM->phase == J9VM_PHASE_NOT_STARTUP)49364937// May need to update the iprofilerMaxCount; this has a higher value in startup4938// mode to minimize overhead, but a higher value in throughput mode.4939// The startup mode for this variable is defined as classLoadPhase AND4940// VM->phase != NOT_STARTUP4941if (interpreterProfilingWasOnAtStartup) // if we used -Xjit:disableInterpreterProfiling don't bother4942{4943int32_t newIprofilerMaxCount = -1;4944//if (persistentInfo->isClassLoadingPhase() && javaVM->phase != J9VM_PHASE_NOT_STARTUP)4945if (javaVM->phase == J9VM_PHASE_EARLY_STARTUP || (persistentInfo->isClassLoadingPhase() && javaVM->phase == J9VM_PHASE_STARTUP))4946{4947if (compInfo->getIprofilerMaxCount() != TR::Options::_maxIprofilingCountInStartupMode)4948newIprofilerMaxCount = TR::Options::_maxIprofilingCountInStartupMode;4949}4950else4951{4952if (compInfo->getIprofilerMaxCount() != TR::Options::_maxIprofilingCount)4953newIprofilerMaxCount = TR::Options::_maxIprofilingCount;4954}4955if (newIprofilerMaxCount != -1) // needs to be updated4956{4957compInfo->setIprofilerMaxCount(newIprofilerMaxCount);49584959j9thread_monitor_enter(javaVM->vmThreadListMutex);4960J9VMThread * currentThread = javaVM->mainThread;4961do {4962currentThread->maxProfilingCount = (UDATA)encodeCount(newIprofilerMaxCount);4963} while ((currentThread = currentThread->linkNext) != javaVM->mainThread);4964j9thread_monitor_exit(javaVM->vmThreadListMutex);49654966if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))4967{4968TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u Changing maxIProfilingCount to %d", (uint32_t)crtElapsedTime, newIprofilerMaxCount);4969}4970}4971} // if (interpreterProfilingWasOnAtStartup)4972} // if (javaVM->phase != J9VM_PHASE_NOT_STARTUP)497349744975if (newState != oldState) // state changed4976{4977persistentInfo->setJitState(newState);4978persistentInfo->setJitStateChangeSampleCount(persistentInfo->getJitTotalSampleCount());4979if ((oldState == IDLE_STATE || oldState == STARTUP_STATE) &&4980(newState != IDLE_STATE && newState != STARTUP_STATE))4981persistentInfo->setJitSampleCountWhenActiveStateEntered(persistentInfo->getJitTotalSampleCount());49824983if (newState == STARTUP_STATE) // I have moved from some state into STARTUP4984{4985persistentInfo->setJitSampleCountWhenStartupStateEntered(persistentInfo->getJitTotalSampleCount());4986if (compInfo->getCpuUtil()->isFunctional())4987persistentInfo->setVmTotalCpuTimeWhenStartupStateEntered(compInfo->getCpuUtil()->getVmTotalCpuTime());4988}4989else4990{4991persistentInfo->setJitSampleCountWhenStartupStateExited(persistentInfo->getJitTotalSampleCount());4992if (compInfo->getCpuUtil()->isFunctional())4993persistentInfo->setVmTotalCpuTimeWhenStartupStateExited(compInfo->getCpuUtil()->getVmTotalCpuTime());4994}499549964997if (newState == IDLE_STATE)4998{4999static char *disableIdleRATCleanup = feGetEnv("TR_disableIdleRATCleanup");5000if (disableIdleRATCleanup == NULL)5001persistentInfo->getRuntimeAssumptionTable()->reclaimMarkedAssumptionsFromRAT(-1);5002}50035004// Logic related to IdleCPU exploitation5005// If I left IDLE state we may set a desired delay to allocate some data structures5006if (oldState == IDLE_STATE)5007{5008if (firstIdleStateAfterStartup) // This flag only gets set once if we happen to be in idle state when we exit JVM startup5009{5010firstIdleStateAfterStartup = false;5011if (TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&5012!compInfo->getLowPriorityCompQueue().isTrackingEnabled())5013{5014uint64_t t = crtElapsedTime + TR::Options::_delayToEnableIdleCpuExploitation;5015if (TR::Options::_compilationDelayTime > 0 && (uint64_t)TR::Options::_compilationDelayTime > t)5016t = TR::Options::_compilationDelayTime;5017timeToAllocateTrackingHT = t;5018}5019}5020}50215022if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))5023{5024TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u JIT changed state from %s to %s cSmpl=%3u iSmpl=%3u comp=%3u recomp=%3u, Q_SZ=%3d CLP=%s jvmCPU=%d%%",5025(uint32_t)crtElapsedTime,5026jitStateNames[oldState], jitStateNames[newState], compInfo->_intervalStats._compiledMethodSamples,5027compInfo->_intervalStats._interpretedMethodSamples,5028compInfo->_intervalStats._numFirstTimeCompilationsInInterval,5029compInfo->_intervalStats._numRecompilationsInInterval,5030compInfo->getMethodQueueSize(),5031persistentInfo->isClassLoadingPhase()?"ON":"OFF",5032avgJvmCpuUtil);5033}50345035// Turn on/off profiling in the jit5036if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableSamplingJProfiling))5037{5038int32_t newProfilingValue = -1;5039if ((oldState == STARTUP_STATE || oldState == IDLE_STATE) &&5040(newState == RAMPUP_STATE || newState == STEADY_STATE))5041newProfilingValue = 1;5042else if ((oldState == RAMPUP_STATE || oldState == STEADY_STATE) &&5043(newState == STARTUP_STATE || newState == IDLE_STATE))5044newProfilingValue = 0;5045if (newProfilingValue != -1)5046{5047//fprintf(stderr, "Changed profiling value to %d\n", newProfilingValue);5048j9thread_monitor_enter(javaVM->vmThreadListMutex);5049J9VMThread * currentThread = javaVM->mainThread;5050do5051{5052currentThread->debugEventData4 = newProfilingValue;5053} while ((currentThread = currentThread->linkNext) != javaVM->mainThread);5054j9thread_monitor_exit(javaVM->vmThreadListMutex);5055}5056}5057}5058if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitState))5059{5060TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u oldState=%s newState=%s cls=%3u ssn=%u tsn=%3u cSmpl=%3u iSmpl=%3u comp=%3u recomp=%3u, Q_SZ=%3d VMSTATE=%d jvmCPU=%d%%",5061(uint32_t)crtElapsedTime,5062jitStateNames[oldState], jitStateNames[newState],5063numClassesLoadedInIntervalNormalized,5064samplesSentNormalized,5065totalSamplesNormalized,5066compInfo->_intervalStats._compiledMethodSamples,5067compInfo->_intervalStats._interpretedMethodSamples,5068compInfo->_intervalStats._numFirstTimeCompilationsInInterval,5069compInfo->_intervalStats._numRecompilationsInInterval,5070compInfo->getMethodQueueSize(),5071javaVM->phase,5072avgJvmCpuUtil);5073}5074if(TR::Options::getVerboseOption(TR_VerboseJitMemory))5075{5076TR_VerboseLog::writeLine(TR_Vlog_MEMORY, "FIXME: Report JIT memory usage\n");5077}50785079// Allocate the tracking hashtable if needed5080// Note that timeToAllocateTrackingHT will be set to something useful only if TR_UseIdleTime option is set5081if (crtElapsedTime >= timeToAllocateTrackingHT)5082{5083compInfo->getLowPriorityCompQueue().startTrackingIProfiledCalls(TR::Options::_numIProfiledCallsToTriggerLowPriComp);5084timeToAllocateTrackingHT = 0xfffffffffffffff0; // never again5085}50865087// Reset stats for next interval5088if (compInfo->getSamplerState() != TR::CompilationInfo::SAMPLER_DEEPIDLE &&5089compInfo->getSamplerState() != TR::CompilationInfo::SAMPLER_IDLE)5090compInfo->_intervalStats.decay();5091else5092compInfo->_intervalStats.reset(); // if we are going to sleep for seconds, do not keep any history5093}50945095/// Determine if CPU throttling may be enabled at this time.5096/// We use this to determine if we need to bother calculating CPU usage.5097bool CPUThrottleEnabled(TR::CompilationInfo *compInfo, uint64_t crtTime)5098{5099// test if feature is enabled5100if (TR::Options::_compThreadCPUEntitlement <= 0)5101return false;51025103// During startup we apply throttling only if enabled5104if (!TR::Options::getCmdLineOptions()->getOption(TR_EnableCompThreadThrottlingDuringStartup) &&5105compInfo->getJITConfig()->javaVM->phase != J9VM_PHASE_NOT_STARTUP)5106return false;51075108// Maybe the user wants to start throttling only after some time5109if (crtTime < (uint64_t)TR::Options::_startThrottlingTime)5110return false;51115112// Maybe the user wants to stop throttling after some time5113if (TR::Options::_stopThrottlingTime != 0 && crtTime >= (uint64_t)TR::Options::_stopThrottlingTime)5114{5115if (compInfo->exceedsCompCpuEntitlement() != TR_no)5116{5117compInfo->setExceedsCompCpuEntitlement(TR_no);5118if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))5119TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Changed throttling value for compilation threads to NO because throttling reached expiration time", (uint32_t)crtTime);5120}5121return false;5122}5123return true;5124}51255126/// Sums up CPU utilization of all compilation thread and write this5127/// value in the compilation info (or -1 in case of error)5128static void DoCalculateOverallCompCPUUtilization(TR::CompilationInfo *compInfo, uint64_t crtTime, J9VMThread *currentThread, int32_t *cpuUtilizationValues)5129{5130// Sum up the CPU utilization of all the compilation threads5131int32_t totalCompCPUUtilization = 0;5132//TODO: Is getArrayOfCompilationInfoPerThread() called after setupCompilationThreads()5133TR::CompilationInfoPerThread * const *arrayOfCompInfoPT = compInfo->getArrayOfCompilationInfoPerThread();51345135for (int32_t i = 0; i < compInfo->getNumUsableCompilationThreads(); i++)5136{5137const CpuSelfThreadUtilization& cpuUtil = arrayOfCompInfoPT[i]->getCompThreadCPU();5138if (cpuUtil.isFunctional())5139{5140// If the last interval ended more than 1.5 second ago, do not include it5141// in the calculations.5142int32_t cpuUtilValue = cpuUtil.computeThreadCpuUtilOverLastNns(1500000000);5143cpuUtilizationValues[i] = cpuUtilValue; // memorize for later5144if (cpuUtilValue >= 0) // if first interval is not done, we read -15145totalCompCPUUtilization += cpuUtilValue;5146}5147else5148{5149totalCompCPUUtilization = -1; // error5150break;5151}5152}5153compInfo->setOverallCompCpuUtilization(totalCompCPUUtilization);5154// Issue tracepoint indicating CPU usage percent (-1 on error)5155Trc_JIT_OverallCompCPU(currentThread, totalCompCPUUtilization);5156// Print the overall comp CPU utilization if the right verbose option is specified5157if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerboseCompilationThreadsDetails))5158{5159TR_VerboseLog::CriticalSection vlogLock;5160TR_VerboseLog::write(TR_Vlog_INFO, "t=%6u TotalCompCpuUtil=%3d%%.", static_cast<uint32_t>(crtTime), totalCompCPUUtilization);5161TR::CompilationInfoPerThread * const *arrayOfCompInfoPT = compInfo->getArrayOfCompilationInfoPerThread();5162for (int32_t i = 0; i < compInfo->getNumUsableCompilationThreads(); i++)5163{5164const CpuSelfThreadUtilization& cpuUtil = arrayOfCompInfoPT[i]->getCompThreadCPU();5165TR_VerboseLog::write(" compThr%d:%3d%% (%2d%%, %2d%%) ", i, cpuUtilizationValues[i], cpuUtil.getThreadLastCpuUtil(), cpuUtil.getThreadPrevCpuUtil());5166if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreadsDetails))5167TR_VerboseLog::write("(%dms, %dms, lastCheckpoint=%u) ",5168static_cast<int32_t>(cpuUtil.getLastMeasurementInterval()) / 1000000,5169static_cast<int32_t>(cpuUtil.getSecondLastMeasurementInterval()) / 1000000,5170cpuUtil.getLowResolutionClockAtLastUpdate());5171}5172TR_VerboseLog::writeLine("");5173}5174}51755176void CalculateOverallCompCPUUtilization(TR::CompilationInfo *compInfo, uint64_t crtTime, J9VMThread *currentThread)5177{5178if (compInfo->getOverallCompCpuUtilization() >= 0) // No error so far5179{5180if (compInfo->getNumUsableCompilationThreads() < 8)5181{5182int32_t cpuUtilizationValues[7];5183DoCalculateOverallCompCPUUtilization(compInfo, crtTime, currentThread, cpuUtilizationValues);5184}5185else5186{5187PORT_ACCESS_FROM_JAVAVM(currentThread->javaVM);51885189int32_t *cpuUtilizationValues = static_cast<int32_t *>(j9mem_allocate_memory(compInfo->getNumUsableCompilationThreads() * sizeof(int32_t), J9MEM_CATEGORY_JIT));5190if (cpuUtilizationValues)5191{5192DoCalculateOverallCompCPUUtilization(compInfo, crtTime, currentThread, cpuUtilizationValues);5193j9mem_free_memory(cpuUtilizationValues);5194}5195}5196}5197}51985199/// Sets a exceedsCompCpuEntitlement flag according to whether the CPU should be throttled5200void CPUThrottleLogic(TR::CompilationInfo *compInfo, uint64_t crtTime)5201{5202const int32_t totalCompCPUUtilization = compInfo->getOverallCompCpuUtilization();5203// Decide whether we want to throttle compilation threads5204// and set the throttle flag if we exceed the valued specified by the user5205if (totalCompCPUUtilization >= 0)5206{5207TR_YesNoMaybe oldThrottleValue = compInfo->exceedsCompCpuEntitlement();5208// Implement some for of hysterisis; once in throttle mode the CPU utilization should5209// be 10 percentage points lower than the target to get out of throttling mode5210bool shouldThrottle = (oldThrottleValue != TR_no && TR::Options::_compThreadCPUEntitlement >= 15) ?5211totalCompCPUUtilization > TR::Options::_compThreadCPUEntitlement - 10 :5212totalCompCPUUtilization > TR::Options::_compThreadCPUEntitlement;5213// We want to avoid situations where we end up throttling and all compilation threads5214// get activated working at full capacity (until, half a second later we discover that we throttle again)5215// The solution is to go into a transient state; so from TR_yes we go into TR_maybe and from TR_maybe we go into TR_no5216compInfo->setExceedsCompCpuEntitlement(shouldThrottle ? TR_yes : oldThrottleValue == TR_yes ? TR_maybe : TR_no);5217// If the value changed we may want to print a message in the vlog5218if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance) &&5219oldThrottleValue != compInfo->exceedsCompCpuEntitlement()) // did the value change?5220{5221TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Changed throttling value for compilation threads to %s because compCPUUtil=%d",5222(uint32_t)crtTime,5223compInfo->exceedsCompCpuEntitlement() == TR_yes ? "YES" : compInfo->exceedsCompCpuEntitlement() == TR_maybe ? "MAYBE" : "NO",5224totalCompCPUUtilization);5225}5226}5227else5228{5229compInfo->setExceedsCompCpuEntitlement(TR_no); // Conservative decision is not to throttle in case of error5230// TODO: add an option to force throttling no matter what the compilation thread utilization looks like5231}5232}52335234/// When many classes are loaded per second (like in Websphere startup)5235/// we would like to decrease the initial level of compilation from warm to cold5236/// The following fragment of code uses a heuristic to detect when we are5237/// in a class loading phase and sets a global variable accordingly5238static void classLoadPhaseLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo, uint32_t diffTime)5239{5240//static uint64_t oldElapsedTime = 0;5241static int32_t oldNumLoadedClasses = 0;5242static int32_t oldNumUserLoadedClasses = 0;5243static int32_t numTicksCapped = 0; // will be capped at 25244static int32_t classLoadRateForFirstInterval;5245static int32_t numCLPQuiesceIntervals = 0;52465247TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();5248int32_t prevNumLoadedClasses = oldNumLoadedClasses;5249int32_t prevNumUserLoadedClasses = oldNumUserLoadedClasses;5250uint64_t crtElapsedTime = persistentInfo->getElapsedTime();52515252TR::Options * cmdLineOptions = TR::Options::getCmdLineOptions();52535254if (cmdLineOptions->getOption(TR_ExperimentalClassLoadPhase))5255{5256// Let's experiment with a class loading phase algorithm that is less cpu and time dependent5257// If a sample occurs between a class loading preinitialize hook and a class load initialize hook then5258// we'll set the class load phase threshold to be true until 'n' more ticks have been seen,5259// where 'n' is TR::Options::_experimentalClassLoadPhaseInterval.5260//5261static int32_t classLoadPhaseCount;5262if (loadingClasses && TR::Options::_experimentalClassLoadPhaseInterval > 0)5263{5264persistentInfo->setClassLoadingPhase(true);5265classLoadPhaseCount = TR::Options::_experimentalClassLoadPhaseInterval;5266}5267else if (classLoadPhaseCount > 0)5268--classLoadPhaseCount;5269else if (persistentInfo->isClassLoadingPhase())5270persistentInfo->setClassLoadingPhase(false);52715272return;5273}52745275else5276{5277oldNumLoadedClasses = persistentInfo->getNumLoadedClasses();5278oldNumUserLoadedClasses = TR::Options::_numberOfUserClassesLoaded;52795280int32_t loadedClasses = persistentInfo->getNumLoadedClasses() - prevNumLoadedClasses;52815282// during WAS5 startup we have 300-500 classes loaded per second (uniprocessor P4/2.2Ghz)5283// caveat: this formula depends on the machine speed (also network issues)5284int classLoadRate = loadedClasses*1000/diffTime;5285if (numTicksCapped < 2)5286{5287if (numTicksCapped == 0)5288{5289// This is the first interval; memorize the classLoadRate for later5290classLoadRateForFirstInterval = classLoadRate;5291}5292else5293{5294// This is the second interval; use the classLoadRate to adjust the classLoadPhaseThreshold5295int32_t variance = TR::Options::_classLoadingPhaseVariance < 100 ? TR::Options::_classLoadingPhaseVariance : 0;5296int32_t newCLPThreshold = (int32_t)(0.01 *5297(TR::Options::_classLoadingPhaseThreshold * (100+variance) -52982 * TR::Options::_classLoadingRateAverage * TR::Options::_classLoadingPhaseThreshold * variance/5299(TR::Options::_classLoadingRateAverage + classLoadRateForFirstInterval)));5300// Scale down even more if the user tells us we have only a fraction of a processor5301newCLPThreshold = newCLPThreshold * TR::Options::_availableCPUPercentage / 100;53025303double scalingFactor = (double)newCLPThreshold/(double)TR::Options::_classLoadingPhaseThreshold;53045305int32_t newSecondaryCLPThreshold = (int32_t)(scalingFactor*TR::Options::_secondaryClassLoadingPhaseThreshold);5306TR::Options::_classLoadingPhaseThreshold = newCLPThreshold;5307TR::Options::_secondaryClassLoadingPhaseThreshold = newSecondaryCLPThreshold;53085309// Scale other thresholds as well. Hmm, not sure this is the right thing to do.5310//TR::Options::_waitTimeToExitStartupMode = (int32_t) (TR::Options::_waitTimeToExitStartupMode/scalingFactor);53115312if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCLP))5313{5314TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"ScalingFactor=%.2f Changed CLPTHreshold to %d secondaryCLPThreshold to %d", scalingFactor, newCLPThreshold, newSecondaryCLPThreshold);5315}53165317// On some platforms, if application startup hints have NOT been used by now5318// turn off the selectiveNoServer feature5319if (TR::Options::getCmdLineOptions()->getOption(TR_TurnOffSelectiveNoOptServerIfNoStartupHint) &&5320!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo) &&5321!TR::Options::getCmdLineOptions()->getOption(TR_DisableSelectiveNoOptServer))5322{5323TR::Options::getCmdLineOptions()->setOption(TR_DisableSelectiveNoOptServer); // Turn this feature off5324TR::Options::getAOTCmdLineOptions()->setOption(TR_DisableSelectiveNoOptServer); // Turn this feature off5325if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))5326TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%u selectiveNoOptServer feature turned off", crtElapsedTime);5327}5328}5329numTicksCapped++;5330}5331bool classLoadPhase = false;5332// needed to figure out the first time we exit grace period5333if (crtElapsedTime >= (uint64_t)persistentInfo->getClassLoadingPhaseGracePeriod())5334{5335if (classLoadRate >= TR::Options::_classLoadingPhaseThreshold)5336{5337classLoadPhase = true;5338numCLPQuiesceIntervals = TR::Options::_numClassLoadPhaseQuiesceIntervals; // reload5339}5340else5341{5342if (numCLPQuiesceIntervals > 0)5343{5344if (classLoadRate >= TR::Options::_secondaryClassLoadingPhaseThreshold)5345{5346classLoadPhase = true;5347numCLPQuiesceIntervals--;5348}5349else5350{5351numCLPQuiesceIntervals = 0;5352}5353}5354}5355}5356// If TR_AssumeStartupPhaseUntilToldNotTo is seen, then we may override previous decision5357if (TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo))5358{5359if (TR::Options::getCmdLineOptions()->getOption(TR_UseStrictStartupHints))5360{5361// presence of the endOfStartup signal alone dictates CLP (and startup)5362classLoadPhase = !persistentInfo->getExternalStartupEndedSignal();5363}5364else5365{5366// If endOfStartup signal didn't come yet, assume CLP (and startup)5367// Otherwise, let the normal CLP algorithm work its course and decide startup5368if (!persistentInfo->getExternalStartupEndedSignal()) // endOfStartup didn't come yet5369classLoadPhase = true;5370}5371}5372if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCLP))5373{5374if ((persistentInfo->isClassLoadingPhase() && !classLoadPhase) ||5375(!persistentInfo->isClassLoadingPhase() && classLoadPhase))5376{5377if (classLoadPhase)5378TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"Entering classLoadPhase");5379else5380TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"Exiting classLoadPhase");5381}5382}5383persistentInfo->setClassLoadingPhase(classLoadPhase);53845385int32_t userLoadedClasses = TR::Options::_numberOfUserClassesLoaded - prevNumUserLoadedClasses;5386TR::Options::_userClassLoadingPhase = (userLoadedClasses*1024/diffTime >= TR::Options::_userClassLoadingPhaseThreshold);53875388if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCLP))5389{5390TR_VerboseLog::writeLineLocked(TR_Vlog_MEMORY,"diffTime %d classes %d userClasses %d threshold %d secondaryThreshold %d",5391diffTime, loadedClasses, userLoadedClasses, TR::Options::_classLoadingPhaseThreshold,5392TR::Options::_secondaryClassLoadingPhaseThreshold);5393}5394}5395}539653975398#if defined(J9VM_INTERP_PROFILING_BYTECODES)5399static void iProfilerActivationLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo)5400{5401//printf("%d\n", interpreterProfilingINTSamples);5402if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))5403{5404if (interpreterProfilingState == IPROFILING_STATE_OFF)5405{5406// Should we turn it ON?5407TR_J9VMBase *fej9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, 0));5408TR_IProfiler *iProfiler = fej9->getIProfiler();5409TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();5410if (iProfiler5411&& iProfiler->getProfilerMemoryFootprint() < TR::Options::_iProfilerMemoryConsumptionLimit5412#if defined(J9VM_OPT_JITSERVER)5413&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER5414#endif5415)5416{5417// Turn on if classLoadPhase became active or5418// if many interpreted samples5419if (persistentInfo->isClassLoadingPhase() ||5420interpreterProfilingINTSamples > TR::Options::_iprofilerReactivateThreshold)5421{5422// Don't turn on during first startup phase5423if (!TR::Options::getCmdLineOptions()->getOption(TR_NoIProfilerDuringStartupPhase) ||5424jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP)5425{5426interpreterProfilingMonitoringWindow = 0;5427turnOnInterpreterProfiling(jitConfig->javaVM, compInfo);5428}5429}5430}5431}5432else // STATE != OFF5433{5434// Should we turn it OFF?5435if (TR::Options::getCmdLineOptions()->getOption(TR_UseOldIProfilerDeactivationLogic))5436{5437if (interpreterProfilingINTSamples > 0 && interpreterProfilingJITSamples > 0)5438{5439if (interpreterProfilingINTSamples <= TR::Options::_iprofilerReactivateThreshold &&5440interpreterProfilingINTSamples > 0) // WHY? we already know this5441interpreterProfilingMonitoringWindow ++;5442else // reset the window5443interpreterProfilingMonitoringWindow = 0;54445445if (interpreterProfilingMonitoringWindow > 60)5446turnOffInterpreterProfiling (jitConfig);5447}5448}5449else5450{5451if (interpreterProfilingINTSamples > 0 || interpreterProfilingJITSamples > 0)5452{5453if (interpreterProfilingINTSamples <= TR::Options::_iprofilerReactivateThreshold &&5454(((float)interpreterProfilingINTSamples) / ((float) (interpreterProfilingINTSamples + interpreterProfilingJITSamples))) < (((float)TR::Options::_iprofilerIntToTotalSampleRatio) / 100))5455interpreterProfilingMonitoringWindow ++;5456else // reset the window5457interpreterProfilingMonitoringWindow = 0;54585459if (interpreterProfilingMonitoringWindow > 60)5460turnOffInterpreterProfiling (jitConfig);5461}5462}5463}5464//printf("interpreter samples %d, jit samples %d, monitor window %d, profiler state = %d\n", interpreterProfilingINTSamples, interpreterProfilingJITSamples, interpreterProfilingMonitoringWindow, interpreterProfilingState);5465interpreterProfilingINTSamples = 0;5466interpreterProfilingJITSamples = 0;5467}5468}5469#endif // J9VM_INTERP_PROFILING_BYTECODES54705471static void initJitGCMapCheckAsyncHook(J9JavaVM * vm, IDATA handlerKey, J9JITConfig *jitConfig)5472{5473TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);5474compInfo->getPersistentInfo()->setGCMapCheckEventHandle(handlerKey);5475}547654775478//int32_t samplerThreadStateFrequencies[TR::CompilationInfo::SAMPLER_LAST_STATE+1] = {0, 2, 1000, 100000, INT_MAX, INT_MAX, -1};5479char* samplerThreadStateNames[TR::CompilationInfo::SAMPLER_LAST_STATE+1] =5480{5481"NOT_INITIALIZED",5482"DEFAULT",5483"IDLE",5484"DEEPIDLE",5485"SUSPENDED",5486"STOPPED",5487"INVALID",5488};54895490/// Method executed by various hooks on application thread5491/// when we should take the samplerThread out of DEEPIDLE/IDLE state5492/// This version does not acquire the vmThreadListMutex assuming that5493/// its caller has already done that5494void getOutOfIdleStatesUnlocked(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason)5495{5496if (compInfo->getSamplerState() != expectedState) // state may have changed when not checked under monitor5497return;5498J9JITConfig * jitConfig = compInfo->getJITConfig();5499TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();5500// Time as maintained by sampling thread will be inaccurate here because5501// sampling thread has slept for a while and didn't have the chance to update time5502// Thus, let's use j9time_current_time_millis() instead5503//persistentInfo->setLastTimeSamplerThreadEnteredIdle(persistentInfo->getElapsedTime());5504PORT_ACCESS_FROM_JITCONFIG(jitConfig);5505uint64_t crtTime = j9time_current_time_millis() - persistentInfo->getStartTime();55065507if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)5508{5509compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_IDLE);5510jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInIdleMode();5511persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);5512}5513else if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_IDLE)5514{5515J9JavaVM * vm = jitConfig->javaVM;5516J9VMRuntimeStateListener *listener = &vm->vmRuntimeStateListener;5517compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_DEFAULT);5518jitConfig->samplingFrequency = TR::Options::getSamplingFrequency();5519persistentInfo->setLastTimeThreadsWereActive(crtTime); // make the sampler thread wait for another 5 sec before entering IDLE again5520uint32_t currentVMState = vm->internalVMFunctions->getVMRuntimeState(vm);55215522if (currentVMState == J9VM_RUNTIME_STATE_IDLE)5523{5524if (vm->internalVMFunctions->updateVMRuntimeState(vm, J9VM_RUNTIME_STATE_ACTIVE) &&5525(TR::Options::getVerboseOption(TR_VerbosePerformance)))5526TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread interrupted and changed VM state to %u", (uint32_t)crtTime, J9VM_RUNTIME_STATE_ACTIVE);5527}5528}55295530// Interrupt the samplerThread5531j9thread_interrupt(jitConfig->samplerThread);5532if (TR::Options::getVerboseOption(TR_VerbosePerformance))5533{5534TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread interrupted and changed state to %s and frequency to %d ms due to %s",5535(uint32_t)crtTime, samplerThreadStateNames[compInfo->getSamplerState()],5536jitConfig->samplingFrequency, reason);5537}5538}55395540/// Method executed by various hooks on application thread5541/// when we should take the samplerThread out of DEEPIDLE state5542/// Side-effect: will acquire/release vmThreadListMutex; note that we should5543/// not use this version in GC hooks because a deadlock may happen5544///5545/// In Balanced, once a mutator thread hits AF it will (only) trigger GC, but will not act as main thread.5546/// However, it is still the one that will request (and wait while the request is completed) exclusive VM access.5547/// Once it acquires it will notify main GC thread (which is sleeping). Main GC wakes up and takes control5548/// driving GC till completion. The mutator thread will just wait on 'control mutex' for notification back5549/// from GC main thread that GC has completed. When resumed, the mutator thread will5550/// release the exclusive VM access and proceed with allocation, and program execution.5551/// It is main GC thread that will invoke the hooks (start/end), but it does not directly hold5552/// 'VM thread list' lock. Mutator thread does it.5553void getOutOfIdleStates(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason)5554{5555// First a cheap test without holding a monitor5556if (compInfo->getSamplerState() == expectedState)5557{5558J9JavaVM * vm = compInfo->getJITConfig()->javaVM;5559// Now acquire the monitor and do another test5560j9thread_monitor_enter(vm->vmThreadListMutex);5561getOutOfIdleStatesUnlocked(expectedState, compInfo, reason);5562j9thread_monitor_exit(vm->vmThreadListMutex);5563}5564}55655566/// This routine is executed with vm->vmThreadListMutex in hand5567void samplerThreadStateLogic(TR::CompilationInfo *compInfo, TR_FrontEnd *fe, int32_t numActiveThreads)5568{5569static bool foundThreadActiveDuringIdleMode = false;5570J9JITConfig * jitConfig = compInfo->getJITConfig();5571TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();5572uint64_t crtTime = persistentInfo->getElapsedTime();5573bool notifyVMThread = false;5574int32_t waitTimeInDeepIdleToNotifyVM = compInfo->getSamplingThreadWaitTimeInDeepIdleToNotifyVM();5575J9JavaVM * vm = jitConfig->javaVM;5576uint32_t currentVMState = vm->internalVMFunctions->getVMRuntimeState(vm);5577uint32_t newVMState = currentVMState;55785579if (numActiveThreads > 0)5580persistentInfo->setLastTimeThreadsWereActive(crtTime);55815582TR::CompilationInfo::TR_SamplerStates samplerState = compInfo->getSamplerState();5583TR::CompilationInfo::TR_SamplerStates newSamplerState = samplerState;55845585TR_ASSERT(samplerState != TR::CompilationInfo::SAMPLER_NOT_INITIALIZED, "samplerThreadStateLogic: sampler must be initialized");5586TR_ASSERT(samplerState != TR::CompilationInfo::SAMPLER_STOPPED, "once stopped, samplerThread cannot call samplerThreadLogic again");55875588// Application threads can set different states5589// 1) DisableJIT --> change state to SUSPENDED5590// 2) EnableJIT --> may change state to DEFAULT5591// 3) Hooks --> may change state from DEEPIDLE to IDLE559255935594// Option to stop the sampling thread after certain number of ticks5595//5596if (TR::Options::_samplingThreadExpirationTime >= 0 &&5597TR::Options::_samplingThreadExpirationTime*1000 < crtTime)5598{5599if (samplerState != TR::CompilationInfo::SAMPLER_SUSPENDED) // Nothing to do if sampler is already suspended5600{5601newSamplerState = TR::CompilationInfo::SAMPLER_SUSPENDED; // samplerThread will pick up the new frequency5602jitConfig->samplingFrequency = MAX_SAMPLING_FREQUENCY; // sampling frequency is signed int so set it to 2^31 - 15603persistentInfo->setLastTimeSamplerThreadWasSuspended(crtTime);5604if (J9VM_RUNTIME_STATE_IDLE == currentVMState)// since sampler is being suspended, bring VM back to active5605newVMState = J9VM_RUNTIME_STATE_ACTIVE;5606}5607}5608else5609{5610switch (samplerState)5611{5612case TR::CompilationInfo::SAMPLER_DEFAULT:5613// We may go IDLE if no active threads for the last 5 seconds5614if (numActiveThreads == 0 &&5615crtTime - persistentInfo->getLastTimeThreadsWereActive() > TR::Options::_waitTimeToEnterIdleMode) // 5 seconds of inactivity5616{5617newSamplerState = TR::CompilationInfo::SAMPLER_IDLE;5618jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInIdleMode(); // sample every 1000 ms5619foundThreadActiveDuringIdleMode = false; // reset this flag when we enter idle mode5620persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);5621}5622break;56235624case TR::CompilationInfo::SAMPLER_IDLE: // we may go DEFAULT or DEEP_IDLE5625if (numActiveThreads > 1 || (numActiveThreads == 1 && foundThreadActiveDuringIdleMode))5626{5627// exit idle mode5628newSamplerState = TR::CompilationInfo::SAMPLER_DEFAULT;5629jitConfig->samplingFrequency = TR::Options::getCmdLineOptions()->getSamplingFrequency();5630if (J9VM_RUNTIME_STATE_IDLE == currentVMState)5631newVMState = J9VM_RUNTIME_STATE_ACTIVE;5632}5633else if (numActiveThreads == 0)5634{5635uint64_t timeInIdle = crtTime - persistentInfo->getLastTimeSamplerThreadEnteredIdle();5636// 50 seconds of IDLE puts us in DEEPIDLE5637int32_t waitTimeToEnterDeepIdle = TR::Options::_waitTimeToEnterDeepIdleMode;5638// However, if we came from DEEP_IDLE and we enter DEEP_IDLE again we may want to wait less5639if (compInfo->getPrevSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)5640waitTimeToEnterDeepIdle >>= 2; // 4 times less (12.5 sec)56415642if (timeInIdle > waitTimeToEnterDeepIdle)5643{5644if (TR::Options::_samplingFrequencyInDeepIdleMode > 0) // setting frequency==0 is a way of disabling DEEPIDLE5645{5646// The JIT will enter DEEP_IDLE5647//5648// Decide whether we need to notify the VM/GC5649// We want to ignore repeated IDLE<-->DEEP_IDLE transitions5650if (compInfo->getPrevSamplerState() != TR::CompilationInfo::SAMPLER_DEEPIDLE)5651{5652persistentInfo->setLastTimeSamplerThreadEnteredDeepIdle(crtTime);5653if (waitTimeInDeepIdleToNotifyVM == 0)5654newVMState = J9VM_RUNTIME_STATE_IDLE;5655}5656else5657{5658if ((J9VM_RUNTIME_STATE_ACTIVE == currentVMState) &&5659(waitTimeInDeepIdleToNotifyVM != -1) &&5660(crtTime - persistentInfo->getLastTimeSamplerThreadEnteredDeepIdle() >= waitTimeInDeepIdleToNotifyVM))5661newVMState = J9VM_RUNTIME_STATE_IDLE;5662}5663// Enter DEEPIDLE5664newSamplerState = TR::CompilationInfo::SAMPLER_DEEPIDLE;5665jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInDeepIdleMode();5666}5667else5668{5669if ((J9VM_RUNTIME_STATE_ACTIVE == currentVMState) &&5670(waitTimeInDeepIdleToNotifyVM != -1) &&5671(timeInIdle >= (waitTimeToEnterDeepIdle + waitTimeInDeepIdleToNotifyVM)))5672newVMState = J9VM_RUNTIME_STATE_IDLE;5673}5674}5675foundThreadActiveDuringIdleMode = false;5676}5677else if (numActiveThreads == 1)5678{5679// This sample will postpone the moment when we can move to DEEPIDLE5680persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);5681// Not enough samples to takes out of idle, but maybe next time5682foundThreadActiveDuringIdleMode = true;5683}5684break;56855686case TR::CompilationInfo::SAMPLER_DEEPIDLE: // we may go IDLE or directly DEFAULT5687if (numActiveThreads > 2)5688{5689newSamplerState = TR::CompilationInfo::SAMPLER_DEFAULT;5690jitConfig->samplingFrequency = TR::Options::getCmdLineOptions()->getSamplingFrequency();5691if (J9VM_RUNTIME_STATE_IDLE == currentVMState)5692newVMState = J9VM_RUNTIME_STATE_ACTIVE;5693}5694else if (numActiveThreads == 1)5695{5696newSamplerState = TR::CompilationInfo::SAMPLER_IDLE;5697jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInIdleMode();5698persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);5699foundThreadActiveDuringIdleMode = true; // another sample in idle mode will take us out of idle5700}5701else5702{5703if ((J9VM_RUNTIME_STATE_ACTIVE == currentVMState) &&5704(waitTimeInDeepIdleToNotifyVM != -1) &&5705(crtTime - persistentInfo->getLastTimeSamplerThreadEnteredDeepIdle() >= waitTimeInDeepIdleToNotifyVM))5706newVMState = J9VM_RUNTIME_STATE_IDLE;5707}5708break;57095710case TR::CompilationInfo::SAMPLER_SUSPENDED: // DisableJIT may request a samplerThread suspension5711newSamplerState = TR::CompilationInfo::SAMPLER_SUSPENDED; // samplerThread will pick up the new frequency5712jitConfig->samplingFrequency = MAX_SAMPLING_FREQUENCY; // sampling frequency is signed int so set it to 2^31 - 15713persistentInfo->setLastTimeSamplerThreadWasSuspended(crtTime);5714if (J9VM_RUNTIME_STATE_IDLE == currentVMState) // since sampler is being suspended, bring VM back to active5715newVMState = J9VM_RUNTIME_STATE_ACTIVE;5716break;57175718default:5719TR_ASSERT(false, "samplerThreadProc: invalid state at this point: %d\n", samplerState);5720// try correction5721compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_DEFAULT);5722jitConfig->samplingFrequency = TR::Options::getCmdLineOptions()->getSamplingFrequency();5723} // end switch5724}572557265727// notify VM thread about state change5728if (newVMState != currentVMState)5729{5730if (vm->internalVMFunctions->updateVMRuntimeState(vm, newVMState) &&5731(TR::Options::getVerboseOption(TR_VerbosePerformance)))5732TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread changed VM state to %u", (uint32_t)crtTime, newVMState);5733}5734// Check whether state has changed5735if (samplerState != newSamplerState)5736{5737compInfo->setSamplerState(newSamplerState);5738if (TR::Options::getVerboseOption(TR_VerbosePerformance))5739{5740TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread changed state to %s and frequency to %d ms",5741(uint32_t)crtTime, samplerThreadStateNames[compInfo->getSamplerState()], jitConfig->samplingFrequency);5742}5743}5744// FIXME:5745// Debug ext for the new fields5746}57475748/// Change inlining aggressiveness based on 'time' since we last entered5749/// JIT startup phase. Inlining aggressiveness is a number between 100 and 05750/// with 100 meaning 'be very aggressive' and 0 meaning 'be very conservative'5751/// 'time' is not wall clock time because the algorithm would be dependent on5752/// machine speed/capability and load. Instead 'time' can be expressed in5753/// terms of CPU cycles consumed by the JVM or number of samples taken5754/// by application threads. Both are a loose measure of how much work the5755/// JVM has done.5756void inlinerAggressivenessLogic(TR::CompilationInfo *compInfo)5757{5758uint64_t crtAbstractTime, abstractTimeStartPoint;5759TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();5760// Abstract time can be measured since we entered startup or since we exited startup5761// If we want the latter then we have to change getVmTotalCpuTimeWhenStartupStateEntered() to getVmTotalCpuTimeWhenStartupStateExited()5762if (TR::Options::getCmdLineOptions()->getOption(TR_UseVmTotalCpuTimeAsAbstractTime))5763{5764if (compInfo->getCpuUtil()->isFunctional())5765{5766crtAbstractTime = compInfo->getCpuUtil()->getVmTotalCpuTime()/1000000; // convert from ns to ms5767abstractTimeStartPoint = persistentInfo->getVmTotalCpuTimeWhenStartupStateEntered()/1000000;5768}5769else // if we cannot get JVM cpu utilization, then the options to tune the algorithm will contain wrong values5770{5771// Force the usage of the other metric5772TR::Options::getCmdLineOptions()->setOption(TR_UseVmTotalCpuTimeAsAbstractTime, false);5773if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))5774TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Changed from JVM time to JIT samples for abstract time measurement");5775// Set default values5776TR::Options::_abstractTimeGracePeriod = DEFAULT_ABSTRACT_TIME_SAMPLES_GRACE_PERIOD;5777TR::Options::_abstractTimeToReduceInliningAggressiveness = DEFAULT_ABSTRACT_TIME_SAMPLES_TO_REDUCE_INLINING_AGGRESSIVENESS;57785779crtAbstractTime = persistentInfo->getJitTotalSampleCount();5780abstractTimeStartPoint = persistentInfo->getJitSampleCountWhenStartupStateEntered();5781}5782}5783else // use samples as abstract time5784{5785crtAbstractTime = persistentInfo->getJitTotalSampleCount();5786abstractTimeStartPoint = persistentInfo->getJitSampleCountWhenStartupStateEntered();5787}578857895790uint64_t abstractTimeElapsed = crtAbstractTime - abstractTimeStartPoint;5791int32_t inliningAggressiveness;5792if (abstractTimeElapsed <= TR::Options::_abstractTimeGracePeriod)5793{5794inliningAggressiveness = 100;5795}5796else if (abstractTimeElapsed >= TR::Options::_abstractTimeGracePeriod + TR::Options::_abstractTimeToReduceInliningAggressiveness)5797{5798inliningAggressiveness = 0;5799}5800else5801{5802inliningAggressiveness = 100 - 100 * (abstractTimeElapsed - (uint64_t)TR::Options::_abstractTimeGracePeriod) / (uint64_t)TR::Options::_abstractTimeToReduceInliningAggressiveness;5803}5804// write the computed inliningAggressiveness somewhere easily accessible5805if (inliningAggressiveness != persistentInfo->getInliningAggressiveness())5806{5807persistentInfo->setInliningAggressiveness(inliningAggressiveness);5808if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))5809TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "inliningAggressiveness changed to %d", inliningAggressiveness);5810}5811}5812581358145815static int32_t J9THREAD_PROC samplerThreadProc(void * entryarg)5816{5817J9JITConfig * jitConfig = (J9JITConfig *) entryarg;5818J9JavaVM * vm = jitConfig->javaVM;5819UDATA samplingPeriod = std::max(static_cast<UDATA>(TR::Options::_minSamplingPeriod), jitConfig->samplingFrequency);5820uint64_t lastProcNumCheck = 0;5821bool idleMode = false;5822uint64_t lastMinuteCheck = 0; // for activities that need to be done rarely (every minute)5823// initialize the startTime and elapsedTime here5824PORT_ACCESS_FROM_JAVAVM(vm);58255826TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);5827TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();58285829persistentInfo->setClassLoadingPhaseGracePeriod(2*TR::Options::_classLoadingPhaseInterval);5830persistentInfo->setStartTime(j9time_current_time_millis());5831persistentInfo->setElapsedTime(0);5832uint64_t oldSyncTime = 0; // ms5833uint64_t crtTime = 0; // cached version of the volatile obtained by persistentInfo->getElapsedTime()58345835J9VMThread *samplerThread = 0;5836int rc = vm->internalVMFunctions->internalAttachCurrentThread5837(vm, &samplerThread, NULL,5838J9_PRIVATE_FLAGS_DAEMON_THREAD | J9_PRIVATE_FLAGS_NO_OBJECT |5839J9_PRIVATE_FLAGS_SYSTEM_THREAD | J9_PRIVATE_FLAGS_ATTACHED_THREAD,5840jitConfig->samplerThread);58415842if (rc != JNI_OK)5843{5844// attach failed5845j9thread_monitor_enter(jitConfig->samplerMonitor);5846compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_FAILED_TO_ATTACH);5847j9thread_monitor_notify_all(jitConfig->samplerMonitor);5848j9thread_exit(jitConfig->samplerMonitor);5849return JNI_ERR; // not reachable5850}5851// Inform the waiting thread that attach was successful5852j9thread_monitor_enter(jitConfig->samplerMonitor);5853compInfo->setSamplerThread(samplerThread);5854compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_ATTACHED);5855j9thread_monitor_notify_all(jitConfig->samplerMonitor);5856j9thread_monitor_exit(jitConfig->samplerMonitor);58575858// Read some stats about SCC. This code could have stayed in aboutToBootstrap,5859// but here we execute it on a separate thread and hide its overhead58605861if (TR::Options::isAnyVerboseOptionSet())5862{5863OMRPORT_ACCESS_FROM_J9PORT(PORTLIB);5864char timestamp[32];5865bool incomplete;5866omrstr_ftime_ex(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", persistentInfo->getStartTime(), OMRSTR_FTIME_FLAG_LOCAL);5867TR_VerboseLog::CriticalSection vlogLock;5868TR_VerboseLog::writeLine(TR_Vlog_INFO, "StartTime: %s", timestamp);5869uint64_t phMemAvail = compInfo->computeAndCacheFreePhysicalMemory(incomplete);5870if (phMemAvail != OMRPORT_MEMINFO_NOT_AVAILABLE)5871TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: %lld MB %s", phMemAvail >> 20, incomplete?"estimated":"");5872else5873TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: Unavailable");5874#if defined(J9VM_OPT_SHARED_CLASSES) && defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT)5875// When we read the SCC data we set isWarmSCC either to Yes or No. Otherwise it remains in maybe state.5876J9SharedClassJavacoreDataDescriptor* javacoreData = compInfo->getAddrOfJavacoreData();5877if (compInfo->isWarmSCC() != TR_maybe && TR::Options::getVerboseOption(TR_VerbosePerformance))5878{5879TR_VerboseLog::writeLine(TR_Vlog_INFO,"Shared Class Cache Information:");5880TR_VerboseLog::writeLine(TR_Vlog_INFO,"\tSCCname:%s SCCpath:%s", javacoreData->cacheName, javacoreData->cacheDir);5881TR_VerboseLog::writeLine(TR_Vlog_INFO,"\tSCC_stats_bytes: size=%u free=%u ROMClass=%u AOTCode=%u AOTData=%u JITHint=%u JITProfile=%u",5882javacoreData->cacheSize,5883javacoreData->freeBytes,5884javacoreData->romClassBytes,5885javacoreData->aotBytes,5886javacoreData->aotDataBytes,5887javacoreData->jitHintDataBytes,5888javacoreData->jitProfileDataBytes);5889TR_VerboseLog::writeLine(TR_Vlog_INFO,"\tSCC_stats_#: ROMClasses=%u AOTMethods=%u AOTDataEntries=%u AOTHints=%u AOTJitProfiles=%u",5890javacoreData->numROMClasses,5891javacoreData->numAOTMethods,5892javacoreData->numAotDataEntries,5893javacoreData->numJitHints,5894javacoreData->numJitProfiles);5895}5896#endif5897if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler))5898{5899TR_VerboseLog::writeLine(TR_Vlog_INFO, "Runtime Instrumentation Information:");5900if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())5901{5902TR_VerboseLog::writeLine(TR_Vlog_INFO, "\tRuntime Instrumentation is Enabled");5903if (compInfo->getPersistentInfo()->isRuntimeInstrumentationRecompilationEnabled())5904{5905TR_VerboseLog::writeLine(TR_Vlog_INFO, "\tRuntime Instrumentation based Recompilation enabled");5906}5907}5908else5909{5910TR_VerboseLog::writeLine(TR_Vlog_INFO, "\tRuntime Instrumentation is not Enabled");5911}5912}59135914if (compInfo->isHypervisorPresent())5915{5916J9HypervisorVendorDetails vendor;5917IDATA res = j9hypervisor_get_hypervisor_info(&vendor);5918TR_VerboseLog::writeLine(TR_Vlog_INFO, "Running on hypervisor %s. CPU entitlement = %3.2f",5919res==0 ? vendor.hypervisorName : "", compInfo->getGuestCpuEntitlement());5920}5921else5922{5923TR_VerboseLog::writeLine(TR_Vlog_INFO, "CPU entitlement = %3.2f", compInfo->getJvmCpuEntitlement());5924}5925} // if (TR::Options::isAnyVerboseOptionSet())59265927if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableScorchingSampleThresholdScalingBasedOnNumProc))5928{5929// We want to become more conservative with scorching compilations for large number of5930// processors because JIT profiling is very taxing due to cache coherence issues5931// For a low number of processors (smaller than lowerBoundNumProc) we want our default5932// scorchingSampleThreshold of 240. For a large number of processors (larger than5933// upperBoundNumProc we want a small scorching threshold, say 60 (conservativeScorchingSampleThreshold)5934// For a number of processors between lowerBoundNumProc and upperBoundNumProc we want5935// to decrease the scorchingSampleThreshold linearly5936if (TR::Compiler->target.numberOfProcessors() <= TR::Options::_lowerBoundNumProcForScaling ||5937TR::Options::_scorchingSampleThreshold <= TR::Options::_conservativeScorchingSampleThreshold)5938{5939// Common case. No change in scorchingSampleThreshold5940}5941else5942{5943if (TR::Compiler->target.numberOfProcessors() >= TR::Options::_upperBoundNumProcForScaling)5944{5945// We want a smaller value for R::Options::_scorchingSampleThreshold5946TR::Options::_scorchingSampleThreshold = TR::Options::_conservativeScorchingSampleThreshold;5947}5948else5949{5950TR::Options::_scorchingSampleThreshold = TR::Options::_conservativeScorchingSampleThreshold +5951(TR::Options::_upperBoundNumProcForScaling - TR::Compiler->target.numberOfProcessors())*5952(TR::Options::_scorchingSampleThreshold - TR::Options::_conservativeScorchingSampleThreshold) /5953(TR::Options::_upperBoundNumProcForScaling - TR::Options::_lowerBoundNumProcForScaling);5954// Note that above we cannot divide by 0 due to the way the if-then-else is structured5955}5956if (TR::Options::isAnyVerboseOptionSet())5957{5958float scorchingCpuTarget = TR::Options::_scorchingSampleThreshold <= TR::Options::_sampleInterval ? 100.0 :5959100.0 * TR::Options::_sampleInterval / TR::Options::_scorchingSampleThreshold;5960TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "scorchingSampleThreshold changed to %d (%3.1f%%)",5961TR::Options::_scorchingSampleThreshold, scorchingCpuTarget);5962}5963}5964}59655966float loadFactorAdjustment = 100.0/(compInfo->getNumTargetCPUs()*TR::Options::_availableCPUPercentage);5967if (TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo))5968{5969persistentInfo->setClassLoadingPhase(true); // start in CLP5970vm->internalVMFunctions->jvmPhaseChange(vm, J9VM_PHASE_STARTUP); // The VM state should be STARTUP5971}5972#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT5973if (vm->javaOffloadSwitchOnWithReasonFunc != 0)5974(*vm->javaOffloadSwitchOnWithReasonFunc)(samplerThread, J9_JNI_OFFLOAD_SWITCH_JIT_SAMPLER_THREAD);5975#endif59765977TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, 0);59785979j9thread_set_name(j9thread_self(), "JIT Sampler");5980while (!shutdownSamplerThread)5981{5982while (!shutdownSamplerThread && // watch for shutdown signals5983j9thread_sleep_interruptable((IDATA) samplingPeriod, 0) == 0) // Anything non-0 is an error condition so we shouldn't do the sampling //!= J9THREAD_INTERRUPTED)5984{5985J9VMThread * currentThread;59865987persistentInfo->updateElapsedTime(samplingPeriod);5988crtTime += samplingPeriod;59895990// periodic chores5991// FIXME: make a constant/macro for the period, and make it 1005992if (crtTime - oldSyncTime >= 100) // every 100 ms5993{5994// There is some imprecision regarding the way we maintain elapsed time5995// hence, we need to correct it periodically5996//5997crtTime = j9time_current_time_millis() - persistentInfo->getStartTime();5998persistentInfo->setElapsedTime(crtTime);5999oldSyncTime = crtTime;60006001TR_DebuggingCounters::transferSmallCountsToTotalCounts();60026003if (TR::Options::_compilationExpirationTime > 0 &&6004!persistentInfo->getDisableFurtherCompilation())6005{6006if (crtTime >= 1000*TR::Options::_compilationExpirationTime)6007{6008persistentInfo->setDisableFurtherCompilation(true) ;6009if (fe->isLogSamplingSet())6010{6011TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING,"Disable further compilation");6012}6013}6014}60156016if (compInfo) // don't need this6017{6018// Implement the watch-dog for the compilation thread6019// We must detect situations where compilation requests get stuck for6020// a long time in the compilation queue, because the priority of the6021// compilation thread is too low6022//6023if (compInfo->dynamicThreadPriority() &&6024compInfo->getCompilationLagUnlocked() == TR::CompilationInfo::LARGE_LAG)6025compInfo->changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 12);6026}60276028int32_t heartbeatInterval = TR::Options::getSamplingHeartbeatInterval();6029if (TR::Options::getVerboseOption(TR_VerboseHeartbeat) && heartbeatInterval > 0)6030{6031compInfo->_stats._heartbeatWindowCount++;6032if (compInfo->_stats._heartbeatWindowCount == heartbeatInterval)6033{6034samplingObservationsLogic(jitConfig, compInfo);6035compInfo->_stats._heartbeatWindowCount = 0;6036}6037}60386039// Default: Every minute6040if (crtTime - lastMinuteCheck >= (TR::Options::_virtualMemoryCheckFrequencySec * 1000))6041{6042lastMinuteCheck = crtTime;6043#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))6044// On 32 bit Windows, Linux, and 31 bit z/OS, monitor the virtual memory available to the user6045lowerCompilationLimitsOnLowVirtualMemory(compInfo, NULL);6046#endif60476048#if defined(J9VM_OPT_SHARED_CLASSES) && defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT)6049// Emit SCC tracepoint6050if (TR::Options::sharedClassCache() && TrcEnabled_Trc_JIT_SCCInfo &&6051vm->sharedClassConfig && vm->sharedClassConfig->getJavacoreData)6052{6053J9SharedClassJavacoreDataDescriptor* scc = compInfo->getAddrOfJavacoreData();6054memset(scc, 0, sizeof(J9SharedClassJavacoreDataDescriptor));6055vm->sharedClassConfig->getJavacoreData(vm, scc); // need to rebuild javacore data or else it will be stale6056Trc_JIT_SCCInfo(samplerThread, scc->cacheName, scc->cacheDir, scc->cacheSize, scc->freeBytes, scc->softMaxBytes,6057scc->romClassBytes, scc->aotBytes, scc->aotDataBytes, scc->jitHintDataBytes, scc->jitProfileDataBytes,6058scc->numROMClasses, scc->numAOTMethods, fe->sharedCache()->getSharedCacheDisabledReason());6059}6060#endif6061} // Default: Every minute6062} // every 100 ms60636064//classLoadPhaseReanalyzed = classLoadPhaseLogic(jitConfig, compInfo); // moved down60656066// TODO: Does this need to be synchronized with the one that happens at shutdown?6067// TODO: If this has too much overhead, it can be added to the6068// "periodic chores" section so it's done less often. I've stuck it here6069// because I'm paranoid about the 32-bit counters overflowing.6070//6071TR::DebugCounterGroup *dynamicCounters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getDynamicCounters();6072if (dynamicCounters)6073dynamicCounters->accumulate();6074if ( TR::Options::getCmdLineOptions()->getDebugCounterWarmupSeconds() > persistentInfo->getLastDebugCounterResetSeconds()6075&& TR::Options::getCmdLineOptions()->getDebugCounterWarmupSeconds() <= crtTime/1000)6076{6077if (TR::Options::isAnyVerboseOptionSet())6078TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Reset debug counters at t=%dms", (int)crtTime);6079persistentInfo->setLastDebugCounterResetSeconds(crtTime/1000);6080if (dynamicCounters)6081dynamicCounters->resetAll();6082TR::DebugCounterGroup *staticCounters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getStaticCounters();6083if (staticCounters)6084staticCounters->resetAll();6085}60866087jitConfig->samplingTickCount++;6088uint32_t numActiveThreads = 0;60896090j9thread_monitor_enter(vm->vmThreadListMutex);6091currentThread = vm->mainThread;60926093do {6094#if defined(J9VM_INTERP_ATOMIC_FREE_JNI)6095if (!currentThread->inNative)6096#endif /* J9VM_INTERP_ATOMIC_FREE_JNI */6097{6098if (currentThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS)6099{6100vm->internalVMFunctions->J9SignalAsyncEvent(vm, currentThread, jitConfig->sampleInterruptHandlerKey);6101currentThread->stackOverflowMark = (UDATA *) J9_EVENT_SOM_VALUE;6102numActiveThreads++;6103}6104}6105} while ((currentThread = currentThread->linkNext) != vm->mainThread);61066107compInfo->_stats._sampleMessagesSent += numActiveThreads;6108compInfo->_intervalStats._samplesSentInInterval += numActiveThreads;6109compInfo->setNumAppThreadsActive(numActiveThreads, crtTime);61106111if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_IDLE ||6112compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)6113compInfo->_stats._ticksInIdleMode++;61146115// number of processors might change6116if (crtTime > lastProcNumCheck + 300000) // every 5 mins6117{6118if (trPersistentMemory && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitMemory))6119trPersistentMemory->printMemStatsToVlog();61206121// time to reevaluate the number of processors6122compInfo->computeAndCacheCpuEntitlement();6123uint32_t tempProc = compInfo->getNumTargetCPUs(); // TODO is this needed?6124//compInfo->setNumTargetCPUs((tempProc = j9sysinfo_get_number_CPUs_by_type(J9PORT_CPU_TARGET)) > 0 ? tempProc : 1);612561266127loadFactorAdjustment = 100.0/(compInfo->getNumTargetCPUs()*TR::Options::_availableCPUPercentage);61286129if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitMemory))6130{6131bool incomplete;6132TR_PersistentMemory *persistentMemory = compInfo->persistentMemory();6133TR_VerboseLog::CriticalSection vlogLock;6134uint64_t phMemAvail = compInfo->computeAndCacheFreePhysicalMemory(incomplete);6135if (phMemAvail != OMRPORT_MEMINFO_NOT_AVAILABLE)6136TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: %lld MB %s", phMemAvail >> 20, incomplete ? "estimated" : "");6137else6138TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: Unavailable");61396140//TR_VerboseLog::writeLine(TR_Vlog_MEMORY,"t=%6u JIT memory usage", (uint32_t)crtTime);6141//TR_VerboseLog::writeLine(TR_Vlog_MEMORY, "FIXME: Report JIT memory usage\n");6142// Show stats on assumptions6143// assumptionTableMutex is not used, so the numbers may be a little off6144TR_VerboseLog::writeLine(TR_Vlog_MEMORY,"\tStats on assumptions:");6145TR_RuntimeAssumptionTable * rat = persistentInfo->getRuntimeAssumptionTable();6146for (int32_t i=0; i < LastAssumptionKind; i++)6147TR_VerboseLog::writeLine(TR_Vlog_MEMORY,"\tAssumptionType=%d allocated=%d reclaimed=%d", i, rat->getAssumptionCount(i), rat->getReclaimedAssumptionCount(i));6148}6149#if defined(WINDOWS) && defined(TR_TARGET_32BIT)6150if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseVMemAvailable))6151{6152J9MemoryInfo memInfo;6153if (j9sysinfo_get_memory_info(&memInfo) == 0 &&6154memInfo.availVirtual != J9PORT_MEMINFO_NOT_AVAILABLE)6155{6156TR_VerboseLog::writeLineLocked(TR_Vlog_MEMORY,"t=%6u VMemAv=%u MB", (uint32_t)crtTime, (uint32_t)(memInfo.availVirtual>>20));6157}6158}6159#endif6160lastProcNumCheck = crtTime;6161}6162uint32_t loadFactor = (uint32_t) ((numActiveThreads==0?1:numActiveThreads)*loadFactorAdjustment);6163persistentInfo->setLoadFactor(loadFactor);6164// if the loadfactor is 0, set a default of 1. This will allow us to6165// temporarily stop the sampling process by setting a very high samplingFrequency6166//6167if (loadFactor == 0)6168loadFactor = 1;61696170// The following may change the state of the samplerThread and the sampling frequency6171// Must be protected by vm->vmThreadListMutex6172samplerThreadStateLogic(compInfo, fe, numActiveThreads);61736174UDATA samplingFreq = jitConfig->samplingFrequency;6175// TODO: Should the sampling frequency types in TR::Options be changed to more closely match the J9JITConfig types?6176samplingPeriod = std::max(static_cast<UDATA>(TR::Options::_minSamplingPeriod), (samplingFreq == MAX_SAMPLING_FREQUENCY) ? samplingFreq : samplingFreq * loadFactor);61776178j9thread_monitor_exit(vm->vmThreadListMutex);61796180// Sample every 10 seconds6181static uint64_t lastTimeCpuUsageCircularBufferUpdated = 0;6182if ((crtTime - lastTimeCpuUsageCircularBufferUpdated) > (TR::Options::_cpuUsageCircularBufferUpdateFrequencySec * 1000))6183{6184lastTimeCpuUsageCircularBufferUpdated = crtTime;61856186if (compInfo->getCpuUtil()->isCpuUsageCircularBufferFunctional())6187compInfo->getCpuUtil()->updateCpuUsageCircularBuffer(jitConfig);6188}61896190// Determine if we need to turn GCR counting off. GCR counting is known to have high overhead.6191// If more than a certain number of GCR induced compilations is queued, turn off counting.6192if (persistentInfo->_countForRecompile) // No need to check if GCR is disabled6193{6194if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods) ||6195TR::Options::getJITCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods))6196{6197if (compInfo->getNumGCRRequestsQueued() > TR::Options::_GCRQueuedThresholdForCounting + GCR_HYSTERESIS)6198{6199persistentInfo->_countForRecompile = 0; // disable counting6200// write a message in the vlog6201if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))6202TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u GCR disabled; GCR queued=%d", (uint32_t)crtTime, compInfo->getNumGCRRequestsQueued());6203}6204}6205}62066207// sample every _classLoadingPhaseInterval (i.e. 500 ms)6208static uint64_t lastTimeClassLoadPhaseAnalyzed = 0;6209uint32_t diffTime = (uint32_t)(crtTime - lastTimeClassLoadPhaseAnalyzed);62106211if (diffTime >= (uint32_t)TR::Options::_classLoadingPhaseInterval) // time to re-analyze6212{6213lastTimeClassLoadPhaseAnalyzed = crtTime;62146215// update the JVM cpu utilization if needed6216if (compInfo->getCpuUtil()->isFunctional())6217compInfo->getCpuUtil()->updateCpuUtil(jitConfig);62186219if (CPUThrottleEnabled(compInfo, crtTime))6220{6221// Calculate CPU utilization and set throttle flag6222// This code needs to stay before jitStateLogic because the decision to throttle6223// application threads (taken in jitStateLogic) depends on the decision to throttle6224// the compilation threads6225CalculateOverallCompCPUUtilization(compInfo, crtTime, samplerThread);6226CPUThrottleLogic(compInfo, crtTime);6227}6228// Check if we need to calculate CPU utilization for debug purposes6229else if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerboseCompilationThreadsDetails) || TrcEnabled_Trc_JIT_CompCPU)6230{6231CalculateOverallCompCPUUtilization(compInfo, crtTime, samplerThread);6232}62336234// Update information about global samples6235if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicSamplingWindow))6236compInfo->getJitSampleInfoRef().update(crtTime, TR::Recompilation::globalSampleCount);62376238// determine whether we're in class-load phase6239classLoadPhaseLogic(jitConfig, compInfo, diffTime);6240// fprintf(stderr, "samplingPeriod=%u numProcs=%u numActiveThreads=%u samplingFrequency=%d\n", samplingPeriod, compInfo->getNumTargetCPUs(), numActiveThreads, jitConfig->samplingFrequency);62416242// compute jit state6243jitStateLogic(jitConfig, compInfo, diffTime); // Update JIT state before going to sleep62446245// detect high code cache occupancy6246TR::CodeCacheManager *manager = TR::CodeCacheManager::instance();6247size_t usedCacheSize = manager->getCurrTotalUsedInBytes();6248size_t threshold = manager->codeCacheConfig().highCodeCacheOccupancyThresholdInBytes();6249if ((usedCacheSize > threshold) && !highCodeCacheOccupancyThresholdReached)6250{6251highCodeCacheOccupancyThresholdReached = true;6252if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerbosePerformance))6253{6254TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u JIT entered high code cache occupancy state", (uint32_t)crtTime);6255}6256}6257else if ((usedCacheSize <= threshold) && highCodeCacheOccupancyThresholdReached)6258{6259highCodeCacheOccupancyThresholdReached = false;6260if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerbosePerformance))6261{6262TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u JIT exited high code cache occupancy state", (uint32_t)crtTime);6263}6264}62656266#if defined(J9VM_INTERP_PROFILING_BYTECODES)6267// iProfilerActivationLogic must stay after classLoadPhaseLogic and jitStateLogic6268iProfilerActivationLogic(jitConfig, compInfo);6269#endif // J9VM_INTERP_PROFILING_BYTECODES6270inlinerAggressivenessLogic(compInfo);6271} // if6272} // while62736274// This thread has been interrupted or shutdownSamplerThread flag was set6275// Sleep just a tiny bit just in case shutdownSamplerThread is set just prior going to sleep6276//6277samplingPeriod = TR::Options::_minSamplingPeriod; // sleep 10 ms and then take new decisions6278// The elapsed time is now different6279crtTime = j9time_current_time_millis()-persistentInfo->getStartTime();6280persistentInfo->setElapsedTime(crtTime);6281oldSyncTime = crtTime;6282}62836284// Sampling thread is destroyed in stage 17 (LIBRARIES_UNLOAD)6285// We better not be holding any monitors at this point6286vm->internalVMFunctions->DetachCurrentThread((JavaVM *) vm);62876288j9thread_monitor_enter(vm->vmThreadListMutex);6289compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_STOPPED);6290j9thread_monitor_exit(vm->vmThreadListMutex);62916292j9thread_monitor_enter(jitConfig->samplerMonitor);6293// Tell the application thread that samplerThread has finished executing6294compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_DESTROYED);6295j9thread_monitor_notify_all(jitConfig->samplerMonitor);62966297#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT6298if (vm->javaOffloadSwitchOffNoEnvWithReasonFunc != 0)6299(*vm->javaOffloadSwitchOffNoEnvWithReasonFunc)(vm, j9thread_self(), J9_JNI_OFFLOAD_SWITCH_JIT_SAMPLER_THREAD);6300#endif63016302j9thread_exit(jitConfig->samplerMonitor); /* exit the monitor and terminate the thread */63036304/* NO GUARANTEED EXECUTION BEYOND THIS POINT */63056306return 0;6307}630863096310void jitHookJNINativeRegistered(J9HookInterface **hookInterface, UDATA eventNum, void *eventData, void *userData)6311{6312J9VMJNINativeRegisteredEvent *event = (J9VMJNINativeRegisteredEvent *) eventData;6313J9VMThread *vmThread = event->currentThread;6314J9Method *method = event->nativeMethod;6315void *newAddress = event->nativeMethodAddress;6316bool somethingWasDone = false;631763186319// First check if a thunk has been compiled for this native6320// If so, go and patch the word in the preprologue6321J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;6322if (jitConfig == 0)6323return; // if a hook gets called after freeJitConfig then not much else we can do63246325TR_FrontEnd *vm = TR_J9VMBase::get(jitConfig, vmThread);6326TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);6327getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "JNI registered");63286329uint8_t *thunkStartPC = (uint8_t *)TR::CompilationInfo::getPCIfCompiled(method);6330if (thunkStartPC)6331{6332// The address in the word immediately before the linkage info6333uintptr_t **addressSlot = (uintptr_t **)(thunkStartPC - (4 + sizeof(uintptr_t)));63346335// Write the address slot6336*addressSlot = (uintptr_t *) newAddress;63376338// Sync/Flush6339TR::CodeGenerator::syncCode((uint8_t*)addressSlot, sizeof(uintptr_t));63406341somethingWasDone = true;6342}63436344// Notify the assumptions table that the native has been registered6345{6346OMR::CriticalSection registerNatives(assumptionTableMutex);6347TR_RuntimeAssumptionTable *rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();6348OMR::RuntimeAssumption **headPtr = rat->getBucketPtr(RuntimeAssumptionOnRegisterNative, TR_RuntimeAssumptionTable::hashCode((uintptr_t)method));6349TR_PatchJNICallSite *cursor = (TR_PatchJNICallSite *)(*headPtr);6350while (cursor)6351{6352if (cursor->matches((uintptr_t)method))6353{6354cursor->compensate(vm, 0, newAddress);6355}6356cursor = (TR_PatchJNICallSite*)cursor->getNext();6357}6358}63596360if (somethingWasDone)6361compInfo->setAllCompilationsShouldBeInterrupted();6362}636363646365static UDATA jitReleaseCodeStackWalkFrame(J9VMThread *vmThread, J9StackWalkState *walkState)6366{6367J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;6368J9JITExceptionTable *metaData = walkState->jitInfo;63696370if (metaData)6371{6372int32_t numBlocks = 0;6373int32_t numLiveBlocks = 0;6374for (OMR::FaintCacheBlock *cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete;6375cursor; cursor = cursor->_next)6376{6377if (metaData == cursor->_metaData)6378{6379cursor->_isStillLive = true;6380//fprintf(stderr, " --ccr-- still live %p\n", cursor->metaData->startPC);6381}6382if (cursor->_isStillLive)6383numLiveBlocks++;6384numBlocks++;6385}63866387// All the remaining blocks are still live - there is nothing6388// to collect. Abort the rest of the stack walk now.6389//6390if (numBlocks == numLiveBlocks)6391return J9_STACKWALK_STOP_ITERATING;6392}63936394return J9_STACKWALK_KEEP_ITERATING;6395}63966397static void jitReleaseCodeStackWalk(OMR_VMThread *omrVMThread, condYieldFromGCFunctionPtr condYield = NULL)63986399{6400J9VMThread *vmThread = (J9VMThread *)omrVMThread->_language_vmthread;6401J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;6402if (!jitConfig)6403return; // not much we can do if the hook is called after freeJitConfig64046405if (!jitConfig->methodsToDelete)6406return; // nothing to do640764086409bool yieldHappened = false;6410bool doStackWalkForThread = true;64116412bool isRealTimeGC = TR::Options::getCmdLineOptions()->realTimeGC();6413do6414{6415J9VMThread *thread = vmThread;6416yieldHappened = false;6417do6418{6419if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))6420doStackWalkForThread = (thread->dropFlags & 0x1) ? false : true;64216422if (doStackWalkForThread)6423{6424J9StackWalkState walkState;6425walkState.flags = J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_SKIP_INLINES;6426walkState.skipCount = 0;6427walkState.frameWalkFunction = jitReleaseCodeStackWalkFrame;6428walkState.walkThread = thread;6429vmThread->javaVM->walkStackFrames(vmThread, &walkState);64306431if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))6432{6433thread->dropFlags |= 0x1;6434yieldHappened = condYield(omrVMThread, J9_GC_METRONOME_UTILIZATION_COMPONENT_JIT);6435}6436}64376438if (!yieldHappened)6439thread = thread->linkNext;6440}6441while ((thread != vmThread) && !yieldHappened);6442}6443while (yieldHappened);644464456446TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);6447TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();6448// Now walk all the faint blocks, and collect the ones that are not still live6449//6450OMR::FaintCacheBlock *cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete;6451OMR::FaintCacheBlock *prev = 0;64526453uintptr_t rangeStartPC = 0;6454uintptr_t rangeEndPC = 0;6455uintptr_t rangeColdStartPC = 0;6456uintptr_t rangeColdEndPC = 0;64576458uintptr_t rangeStartMD = 0;6459uintptr_t rangeEndMD = 0;64606461bool firstRange = true;6462bool coldRangeUninitialized = true;64636464bool hasMethodOverrideAssumptions = false;6465bool hasClassExtendAssumptions = false;6466bool hasClassUnloadAssumptions = false;6467bool hasClassRedefinitionAssumptions = false;64686469cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete;6470prev = 0;6471int32_t condYieldCounter = 0;64726473// cmvc 1927536474// It is not safe to exit this function until all faint records have been processed.6475// If we do the following can happen: (1) method A get compiled and recompiled creating a faint record6476// (2) Method A gets unloaded and both bodies get reclaimed. If the faint block for A is not6477// processed before the end of the GC cycle, a compilation for method B can reuse the exact6478// same spot where method A used to be. When we finally process the faint record for A we6479// will reclaim space belonging to B6480while (cursor/*&& (condYieldCounter < 2)*/)6481{6482if (!cursor->_isStillLive)6483{6484J9JITExceptionTable *metaData = cursor->_metaData;64856486// Remove From List6487if (prev)6488prev->_next = cursor->_next;6489else6490jitConfig->methodsToDelete = (void*) cursor->_next;64916492// Free storage for cursor and the code cache - CAREFUL!! iterating on cursor6493//6494OMR::FaintCacheBlock *next = cursor->_next;6495jitReleaseCodeCollectMetaData(jitConfig, vmThread, metaData, cursor);6496cursor = next;6497if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))6498condYieldCounter += condYield(omrVMThread, J9_GC_METRONOME_UTILIZATION_COMPONENT_JIT);64996500continue;6501}65026503prev = cursor;6504cursor = cursor->_next;6505}65066507/*6508* After we have determined what can be reclaimed for the current pass,6509* we must clear the _isStillLive flag or we will never again consider6510* the faint blocks as candidates for reclaimation.6511*/6512for (cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete; cursor; cursor = cursor->_next)6513{6514cursor->_isStillLive = false;6515}65166517if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))6518{ //clear flags6519J9VMThread *thr = vmThread;6520do6521{6522thr->dropFlags &=0x0;6523thr = thr->linkNext;6524}6525while (thr != vmThread);6526}652765286529}65306531static void jitHookReleaseCodeGlobalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)6532{6533MM_GlobalGCEndEvent *event = (MM_GlobalGCEndEvent *)eventData;6534J9VMThread *vmThread = (J9VMThread*)event->currentThread->_language_vmthread;6535jitReleaseCodeStackWalk(vmThread->omrVMThread);6536jitReclaimMarkedAssumptions(true);6537}65386539static void jitHookReleaseCodeGCCycleEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)6540{6541MM_GCCycleEndEvent *event = (MM_GCCycleEndEvent *)eventData;6542OMR_VMThread *omrVMThread = event->omrVMThread;6543condYieldFromGCFunctionPtr condYield = NULL;6544if (TR::Options::getCmdLineOptions()->realTimeGC())6545condYield = event->condYieldFromGCFunction;65466547jitReleaseCodeStackWalk(omrVMThread,condYield);6548jitReclaimMarkedAssumptions(true);6549}65506551static void jitHookReleaseCodeLocalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)6552{6553MM_LocalGCEndEvent *event = (MM_LocalGCEndEvent *)eventData;6554jitReleaseCodeStackWalk(event->currentThread);6555jitReclaimMarkedAssumptions(true);6556}655765586559/// setupHooks is used in ABOUT_TO_BOOTSTRAP stage (13)6560int32_t setUpHooks(J9JavaVM * javaVM, J9JITConfig * jitConfig, TR_FrontEnd * vm)6561{6562TR::CompilationInfo *compInfo = getCompilationInfo(jitConfig);6563#if defined(J9VM_OPT_JITSERVER)6564if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)6565{6566javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);6567return 0;6568}6569#endif65706571TR_J9VMBase *vmj9 = (TR_J9VMBase *)vm;65726573J9HookInterface * * vmHooks = javaVM->internalVMFunctions->getVMHookInterface(javaVM);6574J9HookInterface * * gcHooks = javaVM->memoryManagerFunctions->j9gc_get_hook_interface(javaVM);6575J9HookInterface * * gcOmrHooks = javaVM->memoryManagerFunctions->j9gc_get_omr_hook_interface(javaVM->omrVM);65766577PORT_ACCESS_FROM_JAVAVM(javaVM);65786579if (TR::Options::getCmdLineOptions()->getOption(TR_noJitDuringBootstrap) ||6580TR::Options::getCmdLineOptions()->getOption(TR_noJitUntilMain) ||6581TR::Options::getCmdLineOptions()->getOption(TR_jitAllAtMain))6582{6583jitConfig->runtimeFlags |= J9JIT_DEFER_JIT;65846585if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_LOOKUP_JNI_ID, jitHookAboutToRunMain, OMR_GET_CALLSITE(), NULL))6586{6587j9tty_printf(PORTLIB, "Error: Unable to install J9HOOK_VM_LOOKUP_JNI_ID hook\n");6588return -1;6589}6590}6591else6592{6593#ifdef J9VM_JIT_SUPPORTS_DIRECT_JNI6594initializeDirectJNI(javaVM);6595#endif6596}65976598// sync the two places for sampling frequency6599jitConfig->samplingFrequency = TR::Options::getSamplingFrequency();66006601if(TR::Options::getCmdLineOptions()->getOption(TR_RTGCMapCheck))6602initJitGCMapCheckAsyncHook(javaVM, javaVM->internalVMFunctions->J9RegisterAsyncEvent(javaVM, jitGCMapCheck, NULL), jitConfig);66036604jitConfig->samplerMonitor = NULL; // initialize this field just in case6605compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_NOT_CREATED); // just in case6606if (jitConfig->samplingFrequency6607&& !vmj9->isAOT_DEPRECATED_DO_NOT_USE()6608#if defined(J9VM_OPT_JITSERVER)6609&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER6610#endif6611)6612{6613if ((jitConfig->sampleInterruptHandlerKey = javaVM->internalVMFunctions->J9RegisterAsyncEvent(javaVM, jitMethodSampleInterrupt, NULL)) < 0)6614{6615j9tty_printf(PORTLIB, "Error: Unable to install method sample handler\n");6616return -1;6617}66186619j9thread_monitor_init_with_name(&(jitConfig->samplerMonitor), 0, "JIT sampling thread");66206621if (jitConfig->samplerMonitor)6622{6623UDATA priority;66246625priority = J9THREAD_PRIORITY_MAX;66266627compInfo->setSamplingThreadWaitTimeInDeepIdleToNotifyVM();6628// Frequency has been set above; now set the state because when the sampler6629// thread is started it must see the new state6630// If the sampler thread cannot be started we must change the state back6631compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_DEFAULT);66326633const UDATA defaultOSStackSize = javaVM->defaultOSStackSize; //256KB stack size66346635if(javaVM->internalVMFunctions->createThreadWithCategory(&jitConfig->samplerThread,6636defaultOSStackSize,6637priority,66380,6639&samplerThreadProc,6640jitConfig,6641J9THREAD_CATEGORY_SYSTEM_JIT_THREAD))6642{6643// cannot create the sampling thread; will continue without6644j9thread_monitor_destroy(jitConfig->samplerMonitor);6645jitConfig->samplerMonitor = 0;6646compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_NOT_INITIALIZED);6647}6648else6649{6650// wait here until the samplingThread attaches to the VM6651j9thread_monitor_enter(jitConfig->samplerMonitor);6652while (compInfo->getSamplingThreadLifetimeState() == TR::CompilationInfo::SAMPLE_THR_NOT_CREATED)6653j9thread_monitor_wait(jitConfig->samplerMonitor);6654j9thread_monitor_exit(jitConfig->samplerMonitor);66556656// At this point the sampling thread either attached successfully and changed the6657// state to SAMPLE_THR_ATTACHED, or failed to attach and exited after changing6658// the state to SAMPLE_THR_FAILED_TO_ATTACH6659if (compInfo->getSamplingThreadLifetimeState() == TR::CompilationInfo::SAMPLE_THR_FAILED_TO_ATTACH) // no monitor needed for this access6660{6661j9thread_monitor_destroy(jitConfig->samplerMonitor);6662jitConfig->samplerMonitor = 0;6663jitConfig->samplerThread = 0;6664compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_NOT_INITIALIZED);6665}6666}6667}66686669if (!jitConfig->samplerMonitor)6670{6671j9tty_printf(PORTLIB, "\nJIT: Method sample thread failed to start -- disabling sampling.\n");6672}6673}6674// If we cannot start the sampling thread or don't want to, then enter NON_STARTUP mode directly6675if (!jitConfig->samplerMonitor)6676javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);66776678if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)6679{6680// JIT_TOSS_CODE is broken. This routine isn't called if it's set...6681j9tty_printf(PORTLIB, "JIT: not installing counting send targets.\n");6682}6683else6684{6685// Do not register the hook that sets method invocation counts in JITServer server mode6686// This ensures that interpreter will not send methods for compilation6687#if defined(J9VM_OPT_JITSERVER)6688if (compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER)6689#endif6690{6691if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_INITIALIZE_SEND_TARGET, jitHookInitializeSendTarget, OMR_GET_CALLSITE(), NULL))6692{6693j9tty_printf(PORTLIB, "Error: Unable to install send target hook\n");6694return -1;6695}6696}6697#if defined (J9VM_INTERP_PROFILING_BYTECODES)6698TR_IProfiler *iProfiler = vmj9->getIProfiler();66996700if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling) &&6701iProfiler && (iProfiler->getProfilerMemoryFootprint() < TR::Options::_iProfilerMemoryConsumptionLimit))6702{6703if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))6704{6705iProfiler->startIProfilerThread(javaVM);6706}6707if (TR::Options::getCmdLineOptions()->getOption(TR_NoIProfilerDuringStartupPhase)6708#if defined(J9VM_OPT_JITSERVER)6709|| compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER6710#endif6711)6712{6713interpreterProfilingState = IPROFILING_STATE_OFF;6714}6715else // start Iprofiler right away6716{6717if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, OMR_GET_CALLSITE(), NULL))6718{6719j9tty_printf(PORTLIB, "Error: Unable to install J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL listener\n");6720return -1;6721}6722interpreterProfilingState = IPROFILING_STATE_ON;6723}67246725interpreterProfilingWasOnAtStartup = true;67266727if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))6728j9tty_printf(PORTLIB, "Succesfully installed J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL listener\n");6729}6730#endif6731if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())6732{6733if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableHWProfilerThread))6734{6735TR_HWProfiler *hwProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->hwProfiler;6736hwProfiler->startHWProfilerThread(javaVM);6737}6738}67396740if (TR::Options::getCmdLineOptions()->getOption(TR_EnableJProfiling) && !TR::Options::getCmdLineOptions()->getOption(TR_DisableJProfilerThread))6741{6742TR_JProfilerThread *jProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->jProfiler;6743jProfiler->start(javaVM);6744}6745}67466747if ((*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_LOCAL_GC_START, jitHookLocalGCStart, OMR_GET_CALLSITE(), NULL) ||6748(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, jitHookLocalGCEnd, OMR_GET_CALLSITE(), NULL) ||6749(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, jitHookGlobalGCStart, OMR_GET_CALLSITE(), NULL) ||6750(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, jitHookGlobalGCEnd, OMR_GET_CALLSITE(), NULL))6751{6752j9tty_printf(PORTLIB, "Error: Unable to register gc hook\n");6753return -1;6754}67556756if (!vmj9->isAOT_DEPRECATED_DO_NOT_USE())6757{67586759IDATA unableToRegisterHooks = 0;67606761if (TR::Options::getCmdLineOptions()->realTimeGC())6762{6763if (!TR::Options::getCmdLineOptions()->getOption(TR_NoClassGC))6764unableToRegisterHooks = (*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_END, jitHookReleaseCodeGCCycleEnd, OMR_GET_CALLSITE(), NULL);6765}6766else6767{6768unableToRegisterHooks =6769((*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, jitHookReleaseCodeGlobalGCEnd, OMR_GET_CALLSITE(), NULL) ||6770(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, jitHookReleaseCodeLocalGCEnd, OMR_GET_CALLSITE(), NULL));6771}67726773if (unableToRegisterHooks)6774{6775j9tty_printf(PORTLIB, "Error: Unable to register gc hook\n");6776return -1;6777}67786779}67806781if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_INTERNAL_CLASS_LOAD, jitHookClassLoad, OMR_GET_CALLSITE(), NULL) ||6782(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_PREINITIALIZE, jitHookClassPreinitialize, OMR_GET_CALLSITE(), NULL) ||6783(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_INITIALIZE, jitHookClassInitialize, OMR_GET_CALLSITE(), NULL))6784{6785j9tty_printf(PORTLIB, "Error: Unable to register class event hook\n");6786return -1;6787}67886789#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)6790if (!vmj9->isAOT_DEPRECATED_DO_NOT_USE())6791{6792#if defined(AOTRT_DLL)6793(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_CLASS_UNLOAD, rtHookClassUnload, NULL);6794(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_CLASS_LOADER_UNLOAD, rtHookClassLoaderUnload, NULL);6795#endif6796if ( (*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_UNLOAD, jitHookClassUnload, OMR_GET_CALLSITE(), NULL) ||6797(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASSES_UNLOAD, jitHookClassesUnload, OMR_GET_CALLSITE(), NULL) ||6798(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_LOADER_UNLOAD, jitHookClassLoaderUnload, OMR_GET_CALLSITE(), NULL) ||6799(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_ANON_CLASSES_UNLOAD, jitHookAnonClassesUnload, OMR_GET_CALLSITE(), NULL) ||6800#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)6801(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_LOADERS_UNLOAD, jitHookClassLoadersUnload, OMR_GET_CALLSITE(), NULL) ||6802#endif6803(*gcHooks)->J9HookRegisterWithCallSite(gcHooks, J9HOOK_MM_INTERRUPT_COMPILATION, jitHookInterruptCompilation, OMR_GET_CALLSITE(), NULL) ||6804(*gcHooks)->J9HookRegisterWithCallSite(gcHooks, J9HOOK_MM_CLASS_UNLOADING_END, jitHookClassesUnloadEnd, OMR_GET_CALLSITE(), NULL))6805{6806j9tty_printf(PORTLIB, "Error: Unable to register class event hook\n");6807return -1;6808}68096810}6811#endif68126813j9thread_monitor_enter(javaVM->vmThreadListMutex);6814if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_CREATED, jitHookThreadCreate, OMR_GET_CALLSITE(), NULL) ||6815(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_END, jitHookThreadEnd, OMR_GET_CALLSITE(), NULL) ||6816(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_CRASH, jitHookThreadCrash, OMR_GET_CALLSITE(), NULL) ||6817(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_DESTROY, jitHookThreadDestroy, OMR_GET_CALLSITE(), NULL) ||6818(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_STARTED, jitHookThreadStart, OMR_GET_CALLSITE(), NULL))6819{6820j9tty_printf(PORTLIB, "Error: Unable to register thread hook\n");6821return -1;6822}6823else6824{6825// FIXME: we should really move the hooking these earlier so that the compilation thread6826// which is created earlier at JIT_INITIALIZED stage also gets the hooks.6827//6828// catch up with the existing threads6829J9VMThread *currThread = javaVM->mainThread;6830if (currThread)6831{6832do6833{6834initThreadAfterCreation(currThread);6835}6836while ((currThread = currThread->linkNext) != javaVM->mainThread);6837}6838}6839j9thread_monitor_exit(javaVM->vmThreadListMutex);68406841#if defined(J9VM_OPT_CRIU_SUPPORT)6842if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_PREPARING_FOR_CHECKPOINT, jitHookPrepareCheckpoint, OMR_GET_CALLSITE(), NULL) ||6843(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_PREPARING_FOR_RESTORE, jitHookPrepareRestore, OMR_GET_CALLSITE(), NULL))6844{6845j9tty_printf(PORTLIB, "Error: Unable to register CRIU hook\n");6846return -1;6847}6848#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */68496850if (!vmj9->isAOT_DEPRECATED_DO_NOT_USE()6851#if defined(J9VM_OPT_JITSERVER)6852&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER6853#endif6854)6855{6856if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_JNI_NATIVE_REGISTERED, jitHookJNINativeRegistered, OMR_GET_CALLSITE(), NULL))6857{6858j9tty_printf(PORTLIB, "Error: Unable to register RegisterNatives hook\n");6859return -1;6860}6861}6862return 0;6863}68646865#if defined(J9VM_OPT_JITSERVER)6866int32_t startJITServer(J9JITConfig *jitConfig)6867{6868J9JavaVM *javaVM = jitConfig->javaVM;6869TR_Listener *listener = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->listener;6870TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);6871PORT_ACCESS_FROM_JAVAVM(javaVM);68726873TR_ASSERT(compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER, "startJITServer cannot be called in non-server mode\n");68746875listener->startListenerThread(javaVM);68766877if (TR::Options::getVerboseOption(TR_VerboseJITServer))6878TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Started JITServer listener thread: %p ", listener->getListenerThread());68796880if (jitConfig->samplingFrequency != 0)6881{6882JITServerStatisticsThread *statsThreadObj = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->statisticsThreadObject;6883// statsThreadObj is guaranteed to be non-null because JITServer will not start if statisticsThreadObject cannot be created6884statsThreadObj->startStatisticsThread(javaVM);6885// Verify that statistics thread was started6886if (!statsThreadObj->getStatisticsThread())6887{6888j9tty_printf(PORTLIB, "Error: Unable to start the statistics thread\n");6889return -1;6890// If we decide to start even without a statistics thread, we must6891// free `statsThreadObj` and set the corresponding jitConfig field to NULL6892}6893}6894return 0;6895}68966897int32_t waitJITServerTermination(J9JITConfig *jitConfig)6898{6899J9JavaVM *javaVM = jitConfig->javaVM;6900TR_Listener *listener = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->listener;6901TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);6902int32_t rc = 0;69036904TR_ASSERT(compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER, "waitJITServerTermination cannot be called in non-server mode\n");69056906rc = listener->waitForListenerThreadExit(javaVM);6907return rc;6908}6909#endif /* J9VM_OPT_JITSERVER */69106911} /* extern "C" */691269136914