Path: blob/master/runtime/compiler/control/CompilationThread.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#define J9_EXTERNAL_TO_VM2324#if SOLARIS || AIXPPC || LINUX || OSX25#include <strings.h>26#define J9OS_STRNCMP strncasecmp27#else28#define J9OS_STRNCMP strncmp29#endif3031#include "control/CompilationThread.hpp"3233#include <exception>34#include <limits.h>35#include <stdlib.h>36#include <time.h>37#include "j9.h"38#include "j9cfg.h"39#include "j9modron.h"40#include "j9protos.h"41#include "vmaccess.h"42#include "objhelp.h"43#include "codegen/CodeGenerator.hpp"44#include "codegen/Instruction.hpp"45#include "codegen/PrivateLinkage.hpp"46#include "compile/CompilationTypes.hpp"47#include "compile/ResolvedMethod.hpp"48#include "control/JitDump.hpp"49#include "control/Recompilation.hpp"50#include "control/RecompilationInfo.hpp"51#include "control/MethodToBeCompiled.hpp"52#include "control/OptimizationPlan.hpp"53#include "env/CompilerEnv.hpp"54#include "env/IO.hpp"55#include "env/PersistentInfo.hpp"56#include "env/StackMemoryRegion.hpp"57#include "env/jittypes.h"58#include "env/ClassTableCriticalSection.hpp"59#include "env/PersistentCHTable.hpp"60#include "env/VMAccessCriticalSection.hpp"61#include "env/VerboseLog.hpp"62#include "compile/CompilationException.hpp"63#include "runtime/CodeCacheExceptions.hpp"64#include "exceptions/JITShutDown.hpp"65#include "exceptions/PersistenceFailure.hpp"66#include "exceptions/LowPhysicalMemory.hpp"67#include "exceptions/RuntimeFailure.hpp"68#include "exceptions/AOTFailure.hpp"69#include "exceptions/FSDFailure.hpp"70#include "exceptions/DataCacheError.hpp"71#include "il/Node.hpp"72#include "il/Node_inlines.hpp"73#include "ilgen/IlGenRequest.hpp"74#include "ilgen/IlGeneratorMethodDetails_inlines.hpp"75#include "infra/CriticalSection.hpp"76#include "infra/MonitorTable.hpp"77#include "infra/Monitor.hpp"78#include "infra/String.hpp"79#include "ras/InternalFunctions.hpp"80#include "runtime/asmprotos.h"81#include "runtime/CodeCache.hpp"82#include "runtime/CodeCacheManager.hpp"83#include "runtime/J9VMAccess.hpp"84#include "runtime/RelocationRuntime.hpp"85#include "runtime/J9Profiler.hpp"86#include "control/CompilationRuntime.hpp"87#include "env/j9method.h"88#include "env/J9SharedCache.hpp"89#include "env/VMJ9.h"90#include "env/annotations/AnnotationBase.hpp"91#include "runtime/MethodMetaData.h"92#include "env/J9JitMemory.hpp"93#include "env/J9SegmentCache.hpp"94#include "env/SystemSegmentProvider.hpp"95#include "env/DebugSegmentProvider.hpp"96#if defined(J9VM_OPT_JITSERVER)97#include "control/JITClientCompilationThread.hpp"98#include "control/JITServerCompilationThread.hpp"99#include "control/JITServerHelpers.hpp"100#include "runtime/JITClientSession.hpp"101#include "runtime/JITServerAOTDeserializer.hpp"102#include "net/ClientStream.hpp"103#include "net/ServerStream.hpp"104#include "omrformatconsts.h"105#endif /* defined(J9VM_OPT_JITSERVER) */106#ifdef COMPRESS_AOT_DATA107#include "shcdatatypes.h" // For CompiledMethodWrapper108#ifdef J9ZOS390109// inflateInit checks the version of the zlib with which data was deflated.110// Reason we need to avoid conversion here is because, we are statically linking111// system zlib which would have encoded String literals in some version which is not112// same as the version we are converting out string literals in. This leads to issue113// where we fail inflating data with version mismatch.114#pragma convlit(suspend)115#include <zlib.h>116#pragma convlit(resume)117#else118#include "zlib.h"119#endif120#endif121#if defined(J9VM_OPT_SHARED_CLASSES)122#include "j9jitnls.h"123#endif124125OMR::CodeCacheMethodHeader *getCodeCacheMethodHeader(char *p, int searchLimit, J9JITExceptionTable* metaData);126extern "C" {127int32_t getCount(J9ROMMethod *romMethod, TR::Options *optionsJIT, TR::Options *optionsAOT);128int32_t encodeCount(int32_t count);129}130static void printCompFailureInfo(TR::Compilation * comp, const char * reason);131132#include "env/ut_j9jit.h"133134#if defined(TR_HOST_S390)135#include <sys/time.h>136#endif137138#if defined(AIXPPC)139#include <unistd.h>140#endif141142#if defined(J9VM_INTERP_PROFILING_BYTECODES)143#include "runtime/IProfiler.hpp"144#endif145146IDATA J9THREAD_PROC compilationThreadProc(void *jitconfig);147IDATA J9THREAD_PROC protectedCompilationThreadProc(J9PortLibrary *portLib, TR::CompilationInfoPerThread*compInfoPT/*void *vmthread*/);148149extern TR::OptionSet *findOptionSet(J9Method *, bool);150151#define VM_STATE_COMPILING 64152#define MAX_NUM_CRASHES 4153#define COMPRESSION_FAILED -1154#define DECOMPRESSION_FAILED -1155#define DECOMPRESSION_SUCCEEDED 0156157#if defined(WINDOWS)158void setThreadAffinity(unsigned _int64 handle, unsigned long mask)159{160if (SetThreadAffinityMask((HANDLE)handle, mask)==0)161{162#ifdef DEBUG163fprintf(stderr, "cannot set affinity mask was %x\n", mask);164#endif165}166}167#endif168169TR_RelocationRuntime*170TR::CompilationInfoPerThreadBase::reloRuntime()171{172#if defined(J9VM_OPT_JITSERVER)173if (_methodBeingCompiled->isAotLoad() ||174_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::NONE ||175(_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && TR::Options::sharedClassCache())) // Enable local AOT compilations at client176return static_cast<TR_RelocationRuntime*>(&_sharedCacheReloRuntime);177return static_cast<TR_RelocationRuntime*>(&_remoteCompileReloRuntime);178#else179return static_cast<TR_RelocationRuntime*>(&_sharedCacheReloRuntime);180#endif /* defined(J9VM_OPT_JITSERVER) */181}182183void184TR::CompilationInfoPerThreadBase::setCompilation(TR::Compilation *compiler)185{186#if defined(DEBUG) || defined(PROD_WITH_ASSUMES)187TR::Compilation *tlsCompiler = TR::comp();188// Exclude PPC LE from the following assert due to xlc compiler bug189TR_ASSERT(190tlsCompiler == compiler || (TR::Compiler->target.cpu.isPower() && TR::Compiler->target.cpu.isLittleEndian()),191"TLS compilation object @ " POINTER_PRINTF_FORMAT " does not match provided compilation object @ " POINTER_PRINTF_FORMAT,192tlsCompiler,193compiler);194#endif195_compiler = compiler;196}197198#if defined(J9VM_OPT_JITSERVER)199thread_local TR::CompilationInfoPerThread *TR::compInfoPT;200#endif /* defined(J9VM_OPT_JITSERVER) */201202static uintptr_t203jitSignalHandler(struct J9PortLibrary *portLibrary, uint32_t gpType, void *gpInfo, void *handler_arg)204{205static int32_t numCrashes = 0;206bool recoverable = true;207J9VMThread *vmThread = (J9VMThread *)handler_arg;208209// Try to find the compilation object210TR::Compilation * comp = 0;211TR_MethodToBeCompiled *methodToBeCompiled = NULL;212J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;213TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);214TR::CompilationInfoPerThread *compInfoPT = compInfo->getCompInfoForThread(vmThread);215if (compInfoPT)216{217comp = compInfoPT->getCompilation();218methodToBeCompiled = compInfoPT->getMethodBeingCompiled();219}220221const char *sig = (comp && comp->signature() ? comp->signature() : "<unknown>");222223TR::MonitorTable *table = TR::MonitorTable::get();224225if (!table ||226!comp ||227(table && !table->isThreadInSafeMonitorState(vmThread)))228recoverable = false;229230static char *alwaysCrash = feGetEnv("TR_NoCrashHandling");231if (alwaysCrash)232recoverable = false;233234// If we have been seeing lots of crashes, bail out, and do not attempt to recover235//236if (numCrashes >= MAX_NUM_CRASHES)237recoverable = false;238239#if defined(DEBUG) || defined(PROD_WITH_ASSUMES)240static char *autoRecover = feGetEnv("TR_CrashHandling");241if (!autoRecover)242recoverable = false;243fprintf(stderr, "JIT: crashed while compiling %s (recoverable %d)\n", sig, recoverable);244#endif245246// For now: disable recovery247//248recoverable = false;249250// Possible return values here are251// J9PORT_SIG_EXCEPTION_CONTINUE_SEARCH -- will cause a crash-dump252// J9PORT_SIG_EXCEPTION_CONTINUE_EXECUTION -- will cause a secondary crash (DO NOT USE THIS)253// J9PORT_SIG_EXCEPTION_RETURN -- abort current compilation gracefully254if (recoverable)255{256numCrashes++;257Trc_JIT_recoverableCrash(vmThread, sig);258return J9PORT_SIG_EXCEPTION_RETURN;259}260Trc_JIT_fatalCrash(vmThread, sig);261262TR_Debug::printStackBacktrace();263264return J9PORT_SIG_EXCEPTION_CONTINUE_SEARCH;265}266#ifdef COMPRESS_AOT_DATA267#ifdef J9ZOS390268#pragma convlit(suspend)269#endif270/*271* \brief272* Inflates the data buffer using zlib into output buffer273*274* \param275* buffer Input buffer that is going to be inflated276*277* \param278* numberOfBytes Size of the data in the input buffer to inflate279*280* \param281* outBuffer Output buffer to hold the deflated data282*283* \param284* unCompressedSize Size of the original data285*286* \return287* Returns DECOMPRESSION_FAILED if it can not inflate the buffer288*289*/290static291int inflateBuffer(U_8 *buffer, int numberOfBytes, U_8 *outBuffer, int unCompressedSize)292{293Bytef *in = (Bytef*)buffer;294Bytef *out = (Bytef*)outBuffer;295z_stream _stream;296_stream.zalloc = Z_NULL;297_stream.zfree = Z_NULL;298_stream.opaque = Z_NULL;299_stream.avail_in = 0;300_stream.next_in = Z_NULL;301int ret = inflateInit(&_stream);302if (ret != Z_OK)303return DECOMPRESSION_FAILED;304_stream.avail_out = unCompressedSize;305_stream.next_out = out;306_stream.next_in = in;307_stream.avail_in = numberOfBytes;308ret = inflate(&_stream, Z_NO_FLUSH);309/**310* ZLIB returns Z_STREAM_END if the buffer stream to be inflated is finished.311* In this case it returns DECOMPRESSION_FAILED.312* Caller of this routine can then decide if they want to retry deflating313* Using larger output buffer.314*/315if (ret != Z_STREAM_END)316{317TR_ASSERT(0, "Fails while inflating buffer");318ret = DECOMPRESSION_FAILED;319}320else321{322ret = DECOMPRESSION_SUCCEEDED;323}324inflateEnd(&_stream);325return ret;326}327328/*329* \brief330* Deflates the data buffer using zlib into output buffer331*332* \param333* buffer Input buffer that is going to be deflated334*335* \param336* numberOfBytes Size of the data in the input buffer to deflate337*338* \param339* outBuffer Output buffer to hold the deflated data340*341* \param342* level Level of compression343*344* \return345* If successful, returns Size of data in the deflated bufer346* else returns COMPRESSION_FAILED347*348*/349static350int deflateBuffer(const U_8 *buffer, int numberOfBytes, U_8 *outBuffer, int level)351{352z_stream _stream;353_stream.zalloc = Z_NULL;354_stream.zfree = Z_NULL;355_stream.opaque = Z_NULL;356int ret=deflateInit(&_stream, level);357if (ret != Z_OK)358return COMPRESSION_FAILED;359// Start deflating360_stream.avail_in = numberOfBytes;361_stream.next_in = (Bytef*) buffer;362_stream.avail_out = numberOfBytes;363_stream.next_out = (Bytef*) outBuffer;364ret = deflate(&_stream, Z_FINISH);365/**366* ZLIB returns Z_STREAM_END if the buffer stream to be deflated is finished.367* That Return COMPRESSION_FAILED in case we are ending up inflating the data.368* Caller of this routine can then decide if they want to retry deflating369* Using larger output buffer.370*/371if ( ret != Z_STREAM_END )372{373TR_ASSERT(0, "Deflated data is larger than original data.");374deflateEnd(&_stream);375return COMPRESSION_FAILED;376}377378int compressedSize = numberOfBytes - _stream.avail_out;379deflateEnd(&_stream);380return compressedSize;381}382#ifdef J9ZOS390383#pragma convlit(resume)384#endif385#endif386inline void387TR::CompilationInfo::incrementMethodQueueSize()388{389_numQueuedMethods++;390// Keep track of maxQueueSize for information purposes391if (_numQueuedMethods > _maxQueueSize)392_maxQueueSize = _numQueuedMethods;393}394395396int32_t TR::CompilationInfo::VERY_SMALL_QUEUE = 2;397int32_t TR::CompilationInfo::SMALL_QUEUE = 4;398int32_t TR::CompilationInfo::MEDIUM_LARGE_QUEUE = 30;399int32_t TR::CompilationInfo::LARGE_QUEUE = 40;400int32_t TR::CompilationInfo::VERY_LARGE_QUEUE = 55;401402TR::CompilationInfo * TR::CompilationInfo::_compilationRuntime = NULL;403404TR_MethodToBeCompiled *405TR::CompilationInfo::getCompilationQueueEntry()406{407TR_MethodToBeCompiled *unusedEntry = NULL;408409// Search for an empty entry in the methodPool. It is possible410// to have entries in the pool which are not fully free'd yet.411// The compile request is completed, and hence the entry is in the pool.412// Once in the pool, the numThreadsWaiting can only decrease.413for (TR_MethodToBeCompiled *cur = _methodPool, *prev = NULL; cur; prev = cur, cur = cur->_next)414{415if (cur->_numThreadsWaiting == 0)416{417unusedEntry = cur;418if (prev)419prev->_next = cur->_next;420else421_methodPool = cur->_next;422--_methodPoolSize;423break;424}425}426427if (!unusedEntry)428{429unusedEntry = TR_MethodToBeCompiled::allocate(_jitConfig);430if (unusedEntry)431unusedEntry->_freeTag = ENTRY_IN_POOL_FREE;432}433434return unusedEntry;435436}437438TR::CompilationInfoPerThread *439TR::CompilationInfo::findFirstLowPriorityCompilationInProgress(CompilationPriority priority) // needs compilationQueueMonitor in hand440{441TR::CompilationInfoPerThread *lowPriorityCompInProgress = NULL;442for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)443{444TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];445TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");446if (curCompThreadInfoPT->getMethodBeingCompiled() &&447curCompThreadInfoPT->getMethodBeingCompiled()->_priority < priority)448{449lowPriorityCompInProgress = curCompThreadInfoPT;450break;451}452} // end for453return lowPriorityCompInProgress;454}455456int32_t TR::CompilationInfo::computeDynamicDumbInlinerBytecodeSizeCutoff(TR::Options *options)457{458// Q_SZ==0 ==> dynamicCutoff=1600459// Q_SZ==32 ==> dynamicCutoff=200460// dynamicCutoff = 1600 - (1600-200)*Q_SZ/32461int32_t cutoff = options->getDumbInlinerBytecodeSizeMaxCutoff() -462(((options->getDumbInlinerBytecodeSizeMaxCutoff() - options->getDumbInlinerBytecodeSizeMinCutoff())*463getMethodQueueSize()) >> 5);464if (cutoff < options->getDumbInlinerBytecodeSizeMinCutoff())465cutoff = options->getDumbInlinerBytecodeSizeMinCutoff();466return cutoff;467}468469// Examine if we need to activate a new thread470// Must have compilation queue monitor in hand when calling this routine471TR_YesNoMaybe TR::CompilationInfo::shouldActivateNewCompThread()472{473// If further compilations have been disabled we could be in a dire situation, for example virtual memory could be474// really low, there could be failures when attempting to allocate persistent memory, a compilation thread could475// have crashed, etc. In such situations we never want to activate a new compilation driven by this API.476if (getPersistentInfo()->getDisableFurtherCompilation())477return TR_no;478479// We must have at least one compilation thread active480if (getNumCompThreadsActive() <= 0)481return TR_yes;482int32_t numCompThreadsSuspended = getNumUsableCompilationThreads() - getNumCompThreadsActive();483TR_ASSERT(numCompThreadsSuspended >= 0, "Accounting error for suspendedCompThreads usable=%d active=%d\n", getNumUsableCompilationThreads(), getNumCompThreadsActive());484// Cannot activate if there is nothing to activate485if (numCompThreadsSuspended <= 0)486return TR_no;487// Do not activate new threads if we are ramping down488if (getRampDownMCT())489return TR_no;490491#ifdef J9VM_OPT_JITSERVER492// Always activate in JITServer server mode493if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)494{495return TR_yes;496}497else if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT &&498getCompThreadActivationPolicy() <= JITServer::CompThreadActivationPolicy::MAINTAIN)499{500return TR_no;501}502#endif503504// Do not activate if we already exceed the CPU enablement for compilation threads505if (exceedsCompCpuEntitlement() != TR_no)506{507// The (- 50) below implements 'rounding', so one compilation thread is considered508// enough for an enablement of [0 - 150]%509if ((getNumCompThreadsActive() + 1) * 100 >= (TR::Options::_compThreadCPUEntitlement + 50))510return TR_no;511}512// Do not activate if we are low on physical memory513bool incompleteInfo;514uint64_t freePhysicalMemorySizeB = computeAndCacheFreePhysicalMemory(incompleteInfo);515if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE &&516freePhysicalMemorySizeB <= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue() + TR::Options::getScratchSpaceLowerBound())517return TR_no;518// Do not activate a new thread during graceperiod if AOT is used and first run because519// we may have too many warm compilations at warm. However, there is no such risk for quickstart520// Another exception: activate if second run in AOT mode521522bool isSecondAOTRun = !TR::Options::getAOTCmdLineOptions()->getOption(TR_NoAotSecondRunDetection) &&523!(numMethodsFoundInSharedCache() < TR::Options::_aotMethodThreshold ||524_statNumAotedMethods > TR::Options::_aotMethodCompilesThreshold);525if (TR::Options::sharedClassCache() &&526!TR::Options::getCmdLineOptions()->isQuickstartDetected() &&527!isSecondAOTRun &&528getPersistentInfo()->getElapsedTime() < (uint64_t)getPersistentInfo()->getClassLoadingPhaseGracePeriod())529return TR_no;530531// Activate if the compilation backlog is large.532// If there is no comp thread starvation or if the number of comp threads was533// determined based on the number of CPUs, then the upper bound of comp threads is _numTargetCPUs-1534// However, if the compilation threads are starved (on Linux) we may want535// to activate additional comp threads irrespective of the CPU entitlement536if (TR::Options::_useCPUsToDetermineMaxNumberOfCompThreadsToActivate)537{538#if defined (J9VM_OPT_JITSERVER)539if (getCompThreadActivationPolicy() == JITServer::CompThreadActivationPolicy::SUBDUE)540{541// If the server reached low memory and then recovered to normal,542// subdue activation of new compilation threads on the client543if (_queueWeight > _compThreadActivationThresholdsonStarvation[getNumCompThreadsActive()] << 1)544return TR_yes;545return TR_no;546}547#endif /* defined(J9VM_OPT_JITSERVER) */548if (getNumCompThreadsActive() < getNumTargetCPUs() - 1)549{550if (_queueWeight > _compThreadActivationThresholds[getNumCompThreadsActive()])551return TR_yes;552}553#if defined(J9VM_OPT_JITSERVER)554else if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && JITServerHelpers::isServerAvailable())555{556557// For JITClient let's be more agressive with compilation thread activation558// because the latencies are larger. Beyond 'numProc-1' we will use the559// 'starvation activation schedule', but accelerated (divide those thresholds by 2)560// NOTE: compilation thread activation policy is AGGRESSIVE if we reached this point561if (_queueWeight > (_compThreadActivationThresholdsonStarvation[getNumCompThreadsActive()] >> 1))562return TR_yes;563}564#endif /* defined(J9VM_OPT_JITSERVER) */565else if (_starvationDetected)566{567// comp thread starvation; may activate threads beyond 'numCpu-1'568if (_queueWeight > _compThreadActivationThresholdsonStarvation[getNumCompThreadsActive()])569return TR_yes;570}571}572else // number of compilation threads indicated by the user573{574if (_queueWeight > _compThreadActivationThresholds[getNumCompThreadsActive()])575return TR_yes;576}577578// Allow the caller to add additional tests if required579return TR_maybe;580}581582bool TR::CompilationInfo::importantMethodForStartup(J9Method *method)583{584if (getMethodBytecodeSize(method) < TR::Options::_startupMethodDontDowngradeThreshold) // filter by size as well585{586// During startup java/lang/String* java/util/zip/* and java/util/Hash* methods are rather important587J9ROMClass *romClazz = J9_CLASS_FROM_METHOD(method)->romClass;588J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClazz);589if (TR::Compiler->target.numberOfProcessors() <= 2)590{591if (J9UTF8_LENGTH(className) == 16 && 0==memcmp(utf8Data(className), "java/lang/String", 16))592return true;593}594else if (J9UTF8_LENGTH(className) >= 14)595{596if (0==memcmp(utf8Data(className), "java/lang/Stri", 14) ||5970==memcmp(utf8Data(className), "java/util/zip/", 14) ||5980==memcmp(utf8Data(className), "java/util/Hash", 14))599{600return true;601}602}603}604return false;605}606607608bool TR::CompilationInfo::shouldDowngradeCompReq(TR_MethodToBeCompiled *entry)609{610bool doDowngrade = false;611TR::IlGeneratorMethodDetails& methodDetails = entry->getMethodDetails();612J9Method *method = methodDetails.getMethod();613#ifdef J9VM_OPT_JITSERVER614TR_ASSERT(getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER, "shouldDowngradeCompReq should not be used by JITServer");615#endif616if (!isCompiled(method) &&617entry->_optimizationPlan->getOptLevel() == warm && // only warm compilations are subject to downgrades618!methodDetails.isMethodInProgress() &&619!methodDetails.isJitDumpMethod() &&620!TR::Options::getCmdLineOptions()->getOption(TR_DontDowngradeToCold))621{622TR::PersistentInfo *persistentInfo = getPersistentInfo();623TR_J9VMBase *fe = TR_J9VMBase::get(_jitConfig, NULL);624const J9ROMMethod * romMethod = methodDetails.getRomMethod(fe);625626// Don't downgrade if method is JSR292 because inlining in those is vital. See CMVC 200145627// However, during start-up phase, allow such downgrades if SCC has been specified on the command line628// (the check for J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES prevents the downgrading when629// the default SCC is used)630if (((_J9ROMMETHOD_J9MODIFIER_IS_SET(romMethod, J9AccMethodHasMethodHandleInvokes)) || fe->isThunkArchetype(method)) &&631(_jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP ||632!TR::Options::sharedClassCache() ||633!J9_ARE_ALL_BITS_SET(jitConfig->javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES)634)635)636{637doDowngrade = false;638}639// perform JNI at cold640else if (entry->isJNINative() ||641// downgrade AOT loads that failed642(entry->_methodIsInSharedCache == TR_yes && entry->_doNotUseAotCodeFromSharedCache && entry->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS))643{644doDowngrade = true;645}646// downgrade during IDLE647else if ((persistentInfo->getJitState() == IDLE_STATE && entry->_jitStateWhenQueued == IDLE_STATE) &&648// but not if the machine uses very little CPU and we want to exploit idle649!(TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&650getCpuUtil() && getCpuUtil()->isFunctional() &&651getCpuUtil()->getCpuUsage() < 10 &&652persistentInfo->getElapsedTime() < 600000) // Downgrade after 10 minutes to conserve CPU in idle mode653)654{655doDowngrade = true;656}657else658{659// We may skip downgrading during grace period660if (TR::Options::getCmdLineOptions()->getOption(TR_DontDowgradeToColdDuringGracePeriod) &&661persistentInfo->getElapsedTime() < (uint64_t)persistentInfo->getClassLoadingPhaseGracePeriod())662{663}664else665{666// Downgrade during CLP when queue grows too large667if ((persistentInfo->isClassLoadingPhase() && getNumQueuedFirstTimeCompilations() > TR::Options::_qsziThresholdToDowngradeDuringCLP) ||668// Downgrade if compilation queue is too large669(TR::Options::getCmdLineOptions()->getOption(TR_EnableDowngradeOnHugeQSZ) &&670getMethodQueueSize() >= TR::Options::_qszThresholdToDowngradeOptLevel) ||671// Downgrade if compilation queue grows too much during startup672(_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&673getMethodQueueSize() >= TR::Options::_qszThresholdToDowngradeOptLevelDuringStartup) ||674// Downgrade if AOT and startup,675(TR::Options::getCmdLineOptions()->sharedClassCache() &&676#if defined(TR_TARGET_POWER) // temporary hack until PPC AOT bug is found677_jitConfig->javaVM->phase == J9VM_PHASE_STARTUP &&678#else679_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&680#endif681!TR::Options::getCmdLineOptions()->getOption(TR_DisableDowngradeToColdOnVMPhaseStartup))682)683{684doDowngrade = true;685}686// Downgrade if RI based recompilation is enabled687else if (persistentInfo->isRuntimeInstrumentationRecompilationEnabled() && // RI and RI Recompilation is functional688!getHWProfiler()->isExpired())689{690#if !defined(J9ZOS390) // disable for zOS because we don't want to increase CPU time691if (!importantMethodForStartup(method)) // Do not downgrade important methods692#endif693{694if (TR::Options::getCmdLineOptions()->getOption(TR_UseRIOnlyForLargeQSZ))695{696TR_HWProfiler *hwProfiler = getHWProfiler();697// Check Q_SZ and downgrade if the backlog is rather large (>_qszMaxThresholdToRIDowngrade)698// If we entered this mode, keep downgrading until Q_SZ drops under _qszMinThresholdToRIDowngrade699int32_t qsz = getMethodQueueSize(); // cache it to avoid inconsistency because it can change700if (qsz > TR::Options::_qszMaxThresholdToRIDowngrade)701{702// Change the threshold to a smaller value to implement hysteresis703// Race conditions are not important here704if (hwProfiler->getQSzThresholdToDowngrade() != TR::Options::_qszMinThresholdToRIDowngrade)705hwProfiler->setQSzThresholdToDowngrade(TR::Options::_qszMinThresholdToRIDowngrade);706}707else if (qsz < TR::Options::_qszMinThresholdToRIDowngrade)708{709// Change the threshold to a bigger value to implement hysteresis710if (hwProfiler->getQSzThresholdToDowngrade() != TR::Options::_qszMaxThresholdToRIDowngrade)711hwProfiler->setQSzThresholdToDowngrade(TR::Options::_qszMaxThresholdToRIDowngrade);712}713if (qsz > hwProfiler->getQSzThresholdToDowngrade())714{715doDowngrade = true;716TR_HWProfiler::_STATS_NumCompDowngradesDueToRI++;717}718}719else if (getHWProfiler()->getProcessBufferState() >= 0 || // Downgrade when RI is on720!TR::Options::getCmdLineOptions()->getOption(TR_DontDowngradeWhenRIIsTemporarilyOff))721{722doDowngrade = true;723// Statistics for how many compilations we downgrade due to RI724TR_HWProfiler::_STATS_NumCompDowngradesDueToRI++;725}726}727}728}729// Always downgrade J9VMInternals because they are expensive730if (!doDowngrade)731{732J9UTF8 * className = J9ROMCLASS_CLASSNAME(methodDetails.getRomClass());733if (J9UTF8_LENGTH(className) == 23 && !memcmp(utf8Data(className), "java/lang/J9VMInternals", 23))734{735doDowngrade = true;736}737}738739// Count methods downgraded while RI buffer processing was off740if (doDowngrade && getPersistentInfo()->isRuntimeInstrumentationEnabled() &&741getHWProfiler()->getProcessBufferState() < 0)742{743getHWProfiler()->incNumDowngradesSinceTurnedOff();744}745}746}747return doDowngrade;748}749750751bool752TR::CompilationInfo::createCompilationInfo(J9JITConfig * jitConfig)753{754TR_ASSERT(!_compilationRuntime, "The global compilation info has already been allocated");755try756{757TR::RawAllocator rawAllocator(jitConfig->javaVM);758void * alloc = rawAllocator.allocate(sizeof(TR::CompilationInfo));759/* FIXME: Replace this with the appropriate initializers in the constructor */760/* Note: there are embedded objects in TR::CompilationInfo that rely on the fact761that we do memset this object to 0 */762memset(alloc, 0, sizeof(TR::CompilationInfo));763_compilationRuntime = new (alloc) TR::CompilationInfo(jitConfig);764765#ifdef DEBUG766if (debug("traceThreadCompile"))767_compilationRuntime->_traceCompiling = true;768#endif769}770catch (const std::exception &e)771{772return false;773}774return true;775}776777void778TR::CompilationInfo::freeAllCompilationThreads()779{780if (_compThreadActivationThresholds)781{782jitPersistentFree(_compThreadActivationThresholds);783}784785if (_compThreadSuspensionThresholds)786{787jitPersistentFree(_compThreadSuspensionThresholds);788}789790if (_compThreadActivationThresholdsonStarvation)791{792jitPersistentFree(_compThreadActivationThresholdsonStarvation);793}794795if (_arrayOfCompilationInfoPerThread)796{797for (int32_t i=0; i < getNumTotalCompilationThreads(); ++i)798{799if (_arrayOfCompilationInfoPerThread[i])800_arrayOfCompilationInfoPerThread[i]->freeAllResources();801}802803jitPersistentFree(_arrayOfCompilationInfoPerThread);804}805}806807void TR::CompilationInfo::freeAllResources()808{809if (_interpSamplTrackingInfo)810{811jitPersistentFree(_interpSamplTrackingInfo);812}813814freeAllCompilationThreads();815}816817void TR::CompilationInfo::freeCompilationInfo(J9JITConfig *jitConfig)818{819TR_ASSERT(_compilationRuntime, "The global compilation info has already been freed.");820TR::CompilationInfo * compilationRuntime = _compilationRuntime;821_compilationRuntime = NULL;822823compilationRuntime->freeAllResources();824825TR::RawAllocator rawAllocator(jitConfig->javaVM);826compilationRuntime->~CompilationInfo();827rawAllocator.deallocate(compilationRuntime);828}829830void TR::CompilationInfoPerThread::freeAllResources()831{832if (_rtLogFile)833{834j9jit_fclose(_rtLogFile);835}836837#if defined(J9VM_OPT_JITSERVER)838if (_classesThatShouldNotBeNewlyExtended)839{840TR_Memory::jitPersistentFree(_classesThatShouldNotBeNewlyExtended);841}842#endif /* defined(J9VM_OPT_JITSERVER) */843}844845#if defined(J9VM_OPT_JITSERVER)846J9ROMClass *847TR::CompilationInfoPerThread::getRemoteROMClassIfCached(J9Class *clazz)848{849return JITServerHelpers::getRemoteROMClassIfCached(getClientData(), clazz);850}851852J9ROMClass *853TR::CompilationInfoPerThread::getAndCacheRemoteROMClass(J9Class *clazz)854{855auto romClass = getRemoteROMClassIfCached(clazz);856if (romClass == NULL)857{858JITServerHelpers::ClassInfoTuple classInfoTuple;859romClass = JITServerHelpers::getRemoteROMClass(clazz, getStream(), getClientData()->persistentMemory(), classInfoTuple);860romClass = JITServerHelpers::cacheRemoteROMClassOrFreeIt(getClientData(), clazz, romClass, classInfoTuple);861TR_ASSERT_FATAL(romClass, "ROM class of J9Class=%p must be cached at this point", clazz);862}863return romClass;864}865#endif /* defined(J9VM_OPT_JITSERVER) */866867void868TR::CompilationInfoPerThread::waitForGCCycleMonitor(bool threadHasVMAccess)869{870#if defined (J9VM_GC_REALTIME)871J9JavaVM *vm = _jitConfig->javaVM;872PORT_ACCESS_FROM_JAVAVM(vm);873j9thread_monitor_enter(vm->omrVM->_gcCycleOnMonitor);874while (vm->omrVM->_gcCycleOn)875{876uint64_t waitTime = 0;877_compInfo.debugPrint(_compilationThread, "GC cycle is on, waiting for the cycle to finish\n");878879if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseGCcycle))880{881waitTime = j9time_hires_clock(); // may not be good for SMP882TR_VerboseLog::writeLineLocked(TR_Vlog_GCCYCLE,"CompilationThread will wait for GC cycle to finish");883}884885// Before waiting on the monitor we need to release VM access (but only if the thread has it)886//887if (threadHasVMAccess)888{889_compInfo.debugPrint(_compilationThread, "\tcompilation thread releasing VM access\n");890releaseVMAccess(_compilationThread);891_compInfo.debugPrint(_compilationThread, "-VMacc\n");892}893894j9thread_monitor_wait(vm->omrVM->_gcCycleOnMonitor);895_compInfo.debugPrint(_compilationThread, "GC cycle is finished, resuming compilation\n");896897if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseGCcycle))898{899// measure the time we spent waiting900waitTime = j9time_hires_delta(waitTime, j9time_hires_clock(), J9PORT_TIME_DELTA_IN_MILLISECONDS);901TR_VerboseLog::writeLineLocked(TR_Vlog_GCCYCLE,"CompilationThread woke up (GC cycle finished); Waiting time = %u msec", (uint32_t)waitTime);902}903904// Acquire VM access905//906if (threadHasVMAccess)907{908j9thread_monitor_exit(vm->omrVM->_gcCycleOnMonitor);909acquireVMAccessNoSuspend(_compilationThread);910_compInfo.debugPrint(_compilationThread, "+VMacc\n");911j9thread_monitor_enter(vm->omrVM->_gcCycleOnMonitor);912}913} // end while914j9thread_monitor_exit(vm->omrVM->_gcCycleOnMonitor);915#endif916}917918extern char *compilationErrorNames[]; // defined in rossa.cpp919920void921TR::CompilationInfoPerThreadBase::setCompilationThreadState(CompilationThreadState v)922{923TR_ASSERT(924_compInfo.getCompilationMonitor()->owned_by_self(),925"Modifying compilation thread state without ownership of the compilation queue monitor"926);927_previousCompilationThreadState = _compilationThreadState;928_compilationThreadState = v;929}930931void932TR::CompilationInfoPerThread::setCompilationThreadState(CompilationThreadState v)933{934TR::CompilationInfoPerThreadBase::setCompilationThreadState(v);935}936937bool938TR::CompilationInfoPerThreadBase::compilationThreadIsActive()939{940bool compThreadIsActive =941_compilationThreadState == COMPTHREAD_ACTIVE942|| _compilationThreadState == COMPTHREAD_SIGNAL_WAIT943|| _compilationThreadState == COMPTHREAD_WAITING;944return compThreadIsActive;945}946947TR::FILE *TR::CompilationInfoPerThreadBase::_perfFile = NULL; // used on Linux for perl tool support948949// Must not be called from different threads in parallel950TR::CompilationInfoPerThreadBase::CompilationInfoPerThreadBase(TR::CompilationInfo &compInfo, J9JITConfig *jitConfig, int32_t id, bool onSeparateThread) :951_compInfo(compInfo),952_jitConfig(jitConfig),953_sharedCacheReloRuntime(jitConfig),954#if defined(J9VM_OPT_JITSERVER)955_remoteCompileReloRuntime(jitConfig),956#endif /* defined(J9VM_OPT_JITSERVER) */957_compThreadId(id),958_onSeparateThread(onSeparateThread),959_vm(NULL),960_methodBeingCompiled(NULL),961_compiler(NULL),962_metadata(NULL),963_reservedDataCache(NULL),964_timeWhenCompStarted(),965_numJITCompilations(),966_qszWhenCompStarted(),967_compilationCanBeInterrupted(false),968_uninterruptableOperationDepth(0),969_compilationThreadState(COMPTHREAD_UNINITIALIZED),970_compilationShouldBeInterrupted(false),971#if defined(J9VM_OPT_JITSERVER)972_cachedClientDataPtr(NULL),973_clientStream(NULL),974_perClientPersistentMemory(NULL),975#endif /* defined(J9VM_OPT_JITSERVER) */976_addToJProfilingQueue(false)977{978// At this point, compilation threads have not been fully started yet. getNumTotalCompilationThreads()979// would not return a correct value. Need to use TR::Options::_numUsableCompilationThreads980TR_ASSERT_FATAL(_compThreadId < (TR::Options::_numUsableCompilationThreads + TR::CompilationInfo::MAX_DIAGNOSTIC_COMP_THREADS),981"Cannot have a compId %d greater than %u", _compThreadId, (TR::Options::_numUsableCompilationThreads + TR::CompilationInfo::MAX_DIAGNOSTIC_COMP_THREADS));982}983984TR::CompilationInfoPerThread::CompilationInfoPerThread(TR::CompilationInfo &compInfo, J9JITConfig *jitConfig, int32_t id, bool isDiagnosticThread)985: TR::CompilationInfoPerThreadBase(compInfo, jitConfig, id, true),986_compThreadCPU(_compInfo.persistentMemory()->getPersistentInfo(), jitConfig, 490000000, id)987{988PORT_ACCESS_FROM_JITCONFIG(jitConfig);989_initializationSucceeded = false;990_osThread = 0;991_compilationThread = 0;992_compThreadPriority = J9THREAD_PRIORITY_USER_MAX;993_compThreadMonitor = TR::Monitor::create("JIT-CompThreadMonitor-??");994_lastCompilationDuration = 0;995996// name the thread997//998// NOTE:999// increasing MAX_*_COMP_THREADS over three digits requires an1000// increase in the length of _activeThreadName and _suspendedThreadName10011002// constant thread name formats1003static const char activeDiagnosticThreadName[] = "JIT Diagnostic Compilation Thread-%03d";1004static const char suspendedDiagnosticThreadName[] = "JIT Diagnostic Compilation Thread-%03d Suspended";1005static const char activeThreadName[] = "JIT Compilation Thread-%03d";1006static const char suspendedThreadName[] = "JIT Compilation Thread-%03d Suspended";10071008const char * selectedActiveThreadName;1009const char * selectedSuspendedThreadName;1010int activeThreadNameLength;1011int suspendedThreadNameLength;10121013// determine the correct name to use, and its length1014//1015// NOTE:1016// using sizeof(...) - 1 because the characters "%3d" will be replaced by three digits;1017// the null character however *is* counted by sizeof1018if (isDiagnosticThread)1019{1020selectedActiveThreadName = activeDiagnosticThreadName;1021selectedSuspendedThreadName = suspendedDiagnosticThreadName;1022activeThreadNameLength = sizeof(activeDiagnosticThreadName) - 1;1023suspendedThreadNameLength = sizeof(suspendedDiagnosticThreadName) - 1;1024_isDiagnosticThread = true;1025}1026else1027{1028selectedActiveThreadName = activeThreadName;1029selectedSuspendedThreadName = suspendedThreadName;1030activeThreadNameLength = sizeof(activeThreadName) - 1;1031suspendedThreadNameLength = sizeof(suspendedThreadName) - 1;1032_isDiagnosticThread = false;1033}10341035_activeThreadName = (char *) j9mem_allocate_memory(activeThreadNameLength, J9MEM_CATEGORY_JIT);1036_suspendedThreadName = (char *) j9mem_allocate_memory(suspendedThreadNameLength, J9MEM_CATEGORY_JIT);10371038if (_activeThreadName && _suspendedThreadName)1039{1040// NOTE:1041// the (char *) casts are done because on Z, sprintf expects1042// a (char *) instead of a (const char *)1043sprintf(_activeThreadName, (char *) selectedActiveThreadName, getCompThreadId());1044sprintf(_suspendedThreadName, (char *) selectedSuspendedThreadName, getCompThreadId());10451046_initializationSucceeded = true;1047}10481049_numJITCompilations = 0;1050_lastTimeThreadWasSuspended = 0;1051_lastTimeThreadWentToSleep = 0;10521053char *rtLogFileName = ((TR_JitPrivateConfig*)jitConfig->privateConfig)->rtLogFileName;1054if (rtLogFileName)1055{1056char fn[1024];10571058bool truncated = TR::snprintfTrunc(fn, sizeof(fn), "%s.%i", rtLogFileName, getCompThreadId());10591060if (!truncated)1061{1062_rtLogFile = fileOpen(TR::Options::getAOTCmdLineOptions(), jitConfig, fn, "wb", true);1063}1064else1065{1066fprintf(stderr, "Did not attempt to open comp thread rtlog %s because filename was truncated\n", fn);1067_rtLogFile = NULL;1068}1069}1070else1071{1072_rtLogFile = NULL;1073}10741075#if defined(J9VM_OPT_JITSERVER)1076_serverVM = NULL;1077_sharedCacheServerVM = NULL;10781079if (compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)1080{1081_classesThatShouldNotBeNewlyExtended = new (PERSISTENT_NEW) PersistentUnorderedSet<TR_OpaqueClassBlock*>(1082PersistentUnorderedSet<TR_OpaqueClassBlock*>::allocator_type(TR::Compiler->persistentAllocator()));1083}1084else1085{1086_classesThatShouldNotBeNewlyExtended = NULL;1087}1088#endif /* defined(J9VM_OPT_JITSERVER) */1089}10901091TR::CompilationInfo::CompilationInfo(J9JITConfig *jitConfig) :1092#if defined(J9VM_OPT_JITSERVER)1093_sslKeys(decltype(_sslKeys)::allocator_type(TR::Compiler->persistentAllocator())),1094_sslCerts(decltype(_sslCerts)::allocator_type(TR::Compiler->persistentAllocator())),1095_classesCachedAtServer(decltype(_classesCachedAtServer)::allocator_type(TR::Compiler->persistentAllocator())),1096#endif /* defined(J9VM_OPT_JITSERVER) */1097_persistentMemory(pointer_cast<TR_PersistentMemory *>(jitConfig->scratchSegment)),1098_sharedCacheReloRuntime(jitConfig),1099_samplingThreadWaitTimeInDeepIdleToNotifyVM(-1),1100_numDiagnosticThreads(0),1101_numCompThreads(0),1102_arrayOfCompilationInfoPerThread(NULL)1103{1104// The object is zero-initialized before this method is called1105//1106::jitConfig = jitConfig;1107_jitConfig = jitConfig;11081109// For normal case with compilation on application thread this1110// initialization will be done later after we are sure that1111// the options have been processed11121113_vmStateOfCrashedThread = 0;11141115_cachedFreePhysicalMemoryB = 0;1116_cachedIncompleteFreePhysicalMemory = false;1117OMRPORT_ACCESS_FROM_J9PORT(jitConfig->javaVM->portLibrary);1118_cgroupMemorySubsystemEnabled = (OMR_CGROUP_SUBSYSTEM_MEMORY == omrsysinfo_cgroup_are_subsystems_enabled(OMR_CGROUP_SUBSYSTEM_MEMORY));1119_suspendThreadDueToLowPhysicalMemory = false;11201121// Initialize the compilation monitor1122//1123_compilationMonitor = TR::Monitor::create("JIT-CompilationQueueMonitor");1124_schedulingMonitor = TR::Monitor::create("JIT-SchedulingMonitor");1125#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)1126_dltMonitor = TR::Monitor::create("JIT-DLTmonitor");1127#endif1128_iprofilerBufferArrivalMonitor = TR::Monitor::create("JIT-IProfilerBufferArrivalMonitor");1129_classUnloadMonitor = TR::MonitorTable::get()->getClassUnloadMonitor(); // by this time this variable is initialized1130// TODO: hang these monitors to something persistent1131_j9MonitorTable = TR::MonitorTable::get();11321133_gpuInitMonitor = TR::Monitor::create("JIT-GpuInitializationMonitor");1134_persistentMemory->getPersistentInfo()->setGpuInitializationMonitor(_gpuInitMonitor);11351136_iprofilerMaxCount = TR::Options::_maxIprofilingCountInStartupMode;11371138PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);1139_cpuUtil = 0; // Field will be set in onLoadInternal after option processing1140static char *verySmallQueue = feGetEnv("VERY_SMALL_QUEUE");1141if (verySmallQueue)1142{1143int temp = atoi(verySmallQueue);1144if (temp)1145VERY_SMALL_QUEUE = temp;1146}1147static char *smallQueue = feGetEnv("SMALL_QUEUE");1148if (smallQueue)1149{1150int temp = atoi(smallQueue);1151if (temp)1152SMALL_QUEUE = temp;1153}1154static char *mediumLargeQueue = feGetEnv("MEDIUM_LARGE_QUEUE");1155if (mediumLargeQueue)1156{1157int temp = atoi(mediumLargeQueue);1158if (temp)1159MEDIUM_LARGE_QUEUE = temp;1160}1161static char *largeQueue = feGetEnv("LARGE_QUEUE");1162if (largeQueue)1163{1164int temp = atoi(largeQueue);1165if (temp)1166LARGE_QUEUE = temp;1167}1168static char *veryLargeQueue = feGetEnv("VERY_LARGE_QUEUE");1169if (veryLargeQueue)1170{1171int temp = atoi(veryLargeQueue);1172if (temp)1173VERY_LARGE_QUEUE = temp;1174}1175statCompErrors.init("CompilationErrors", compilationErrorNames, 0);11761177setSamplerState(TR::CompilationInfo::SAMPLER_NOT_INITIALIZED);11781179setIsWarmSCC(TR_maybe);1180_cpuEntitlement.init(jitConfig);1181_lowPriorityCompilationScheduler.setCompInfo(this);1182_JProfilingQueue.setCompInfo(this);1183_interpSamplTrackingInfo = new (PERSISTENT_NEW) TR_InterpreterSamplingTracking(this);1184#if defined(J9VM_OPT_JITSERVER)1185_clientSessionHT = NULL; // This will be set later when options are processed1186_unloadedClassesTempList = NULL;1187_illegalFinalFieldModificationList = NULL;1188_newlyExtendedClasses = NULL;1189_sequencingMonitor = TR::Monitor::create("JIT-SequencingMonitor");1190_classesCachedAtServerMonitor = TR::Monitor::create("JIT-ClassesCachedAtServerMonitor");1191_compReqSeqNo = 0;1192_chTableUpdateFlags = 0;1193_localGCCounter = 0;1194_activationPolicy = JITServer::CompThreadActivationPolicy::AGGRESSIVE;1195_sharedROMClassCache = NULL;1196_JITServerAOTCacheMap = NULL;1197_JITServerAOTDeserializer = NULL;1198#endif /* defined(J9VM_OPT_JITSERVER) */1199}12001201TR::CompilationInfoPerThreadBase *TR::CompilationInfo::getCompInfoWithID(int32_t ID)1202{1203for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)1204{1205TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];1206TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");12071208if (curCompThreadInfoPT->getCompThreadId() == ID)1209return curCompThreadInfoPT;1210}12111212return NULL;1213}12141215// Must hold compilation queue monitor when calling this method1216//1217TR::CompilationInfoPerThread *TR::CompilationInfo::getFirstSuspendedCompilationThread() // MCT1218{1219for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)1220{1221TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];1222TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");12231224CompilationThreadState currentState = curCompThreadInfoPT->getCompilationThreadState();1225if (currentState == COMPTHREAD_SUSPENDED ||1226currentState == COMPTHREAD_SIGNAL_SUSPEND)1227return curCompThreadInfoPT;1228}12291230return NULL;1231}12321233TR::Compilation *TR::CompilationInfo::getCompilationWithID(int32_t ID)1234{1235TR::CompilationInfoPerThreadBase *ciptb = getCompInfoWithID(ID);1236return ciptb ? ciptb->getCompilation() : NULL;1237}12381239void TR::CompilationInfo::setAllCompilationsShouldBeInterrupted()1240{1241for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)1242{1243TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];1244TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");12451246curCompThreadInfoPT->setCompilationShouldBeInterrupted(GC_COMP_INTERRUPT);1247}12481249_lastCompilationsShouldBeInterruptedTime = getPersistentInfo()->getElapsedTime(); // RAS1250}12511252bool TR::CompilationInfo::asynchronousCompilation()1253{1254static bool answer = (!TR::Options::getJITCmdLineOptions()->getOption(TR_DisableAsyncCompilation) &&1255TR::Options::getJITCmdLineOptions()->getInitialBCount() &&1256TR::Options::getJITCmdLineOptions()->getInitialCount() &&1257TR::Options::getAOTCmdLineOptions()->getInitialSCount() &&1258TR::Options::getAOTCmdLineOptions()->getInitialBCount() &&1259TR::Options::getAOTCmdLineOptions()->getInitialCount()1260);1261return answer;1262}12631264TR_YesNoMaybe TR::CompilationInfo::detectCompThreadStarvation()1265{1266// If compilation queue is small, then we don't care about comp thread starvation1267if (getOverallQueueWeight() < TR::Options::_queueWeightThresholdForStarvation)1268return TR_no;1269// If compilation threads already consume too much CPU, do not throttle application threads1270if (exceedsCompCpuEntitlement() != TR_no)1271return TR_no;1272// If the state is IDLE we cannot starve the compilation threads1273//if (getPersistentInfo()->getJitState() == IDLE_STATE)1274// return TR_no;12751276// If there are idle cycles on the CPU set where this JVM can run1277// then the compilation threads should be able to use those cycles1278// The following is just an approximation because we look at idle1279// cyles on the entire machine1280if (getCpuUtil()->isFunctional() &&1281getCpuUtil()->getAvgCpuIdle() > 5 && // This is for the entire machine1282getCpuUtil()->getVmCpuUsage() + 10 < getJvmCpuEntitlement()) // at least 10% unutilized by this JVM1283return TR_no;12841285// Large queue and small CPU utilization for the compilation thread1286// is a sign of compilation thread starvation1287// TODO: augment the logic with CPU utilization and number of CPUs allowed to use12881289// Find compilation threads that are not suspended and look at their CPU utilization1290// NOTE: normally we need to acquire the compQMonitor when looking at comp thread state1291// Here we allow a small imprecision because it's just a heuristic1292// We count on the fact that threads never get deleted1293int32_t totalCompCpuUtil = 0;1294int32_t numActive = 0;1295TR_YesNoMaybe answer = TR_maybe;1296bool compCpuFunctional = true;1297for (int32_t compId = 0; compId < _numCompThreads; compId++)1298{1299// We must look at all active threads because we want to avoid the1300// case where they compete with each other (4 comp threads on a single processor)1301//1302TR::CompilationInfoPerThread *compInfoPT = _arrayOfCompilationInfoPerThread[compId];1303TR_ASSERT(compInfoPT, "compInfoPT must exist because we don't destroy compilation threads");1304if (compInfoPT->compilationThreadIsActive())1305{1306numActive++;1307int32_t compCpuUtil = compInfoPT->getCompThreadCPU().getThreadLastCpuUtil();1308if (compCpuUtil >= 0) // when not functional or too soon to tell the answer is negative1309{1310totalCompCpuUtil += compCpuUtil;1311if (compCpuUtil >= TR::Options::_cpuUtilThresholdForStarvation) // 25%1312answer = TR_no; // Good utilization for at least one thread; no reason to make app threads sleep1313}1314else1315{1316compCpuFunctional = false;1317}1318}1319}1320_totalCompThreadCpuUtilWhenStarvationComputed = totalCompCpuUtil; // RAS1321_numActiveCompThreadsWhenStarvationComputed = numActive; // RAS132213231324if (answer == TR_maybe && compCpuFunctional) // Didn't reach a conclusion yet1325{1326if (getCpuUtil()->isFunctional())1327{1328// If the CPU utilization of all the active compilation threads is at least1329// half of the JVM utilization of the JVM, then compilation threads are not starved1330if ((totalCompCpuUtil << 1) >= getCpuUtil()->getVmCpuUsage())1331{1332answer = TR_no;1333}1334else // If all compilation threads are using less than 75% CPU then we declare starvation1335{1336if (totalCompCpuUtil < 75)1337answer = TR_yes;1338}1339}1340}1341return answer;1342}13431344// This should be called only if detectCompThreadStarvation returns TR_yes1345int32_t TR::CompilationInfo::computeAppSleepNano() const1346{1347int32_t QW = getOverallQueueWeight();1348if (QW < TR::Options::_queueWeightThresholdForAppThreadYield)1349return 0;13501351// I don't like to throttle application threads if I can still activate comp threads.1352int32_t numCompThreadsSuspended = getNumUsableCompilationThreads() - getNumCompThreadsActive();1353if (numCompThreadsSuspended > 0)1354return 0;13551356if (QW < 4*TR::Options::_queueWeightThresholdForAppThreadYield)1357return (250000*(QW/TR::Options::_queueWeightThresholdForAppThreadYield));1358else return 1000000;1359}13601361void TR::CompilationInfo::vlogAcquire()1362{1363if (!_vlogMonitor)1364_vlogMonitor = TR::Monitor::create("JIT-VerboseLogMonitor");13651366if (_vlogMonitor)1367_vlogMonitor->enter();1368}13691370void TR::CompilationInfo::vlogRelease()1371{1372if (_vlogMonitor)1373_vlogMonitor->exit();1374}13751376void TR::CompilationInfo::rtlogAcquire()1377{1378if (!_rtlogMonitor)1379_rtlogMonitor = TR::Monitor::create("JIT-RunTimeLogMonitor");13801381if (_rtlogMonitor)1382_rtlogMonitor->enter();1383}13841385void TR::CompilationInfo::rtlogRelease()1386{1387if (_rtlogMonitor)1388_rtlogMonitor->exit();1389}13901391void TR::CompilationInfo::acquireCompMonitor(J9VMThread *vmThread) // used when we know we have a compilation monitor1392{1393getCompilationMonitor()->enter();1394}13951396void TR::CompilationInfo::releaseCompMonitor(J9VMThread *vmThread) // used when we know we have a compilation monitor1397{1398getCompilationMonitor()->exit();1399}14001401void TR::CompilationInfo::waitOnCompMonitor(J9VMThread *vmThread)1402{1403getCompilationMonitor()->wait();1404}14051406intptr_t TR::CompilationInfo::waitOnCompMonitorTimed(J9VMThread *vmThread, int64_t millis, int32_t nanos)1407{1408intptr_t retCode;1409retCode = getCompilationMonitor()->wait_timed(millis, nanos);1410return retCode;1411}14121413void TR::CompilationInfo::acquireCompilationLock()1414{1415if (_compilationMonitor)1416{1417acquireCompMonitor(0);1418debugPrint("\t\texternal user acquiring compilation monitor\n");1419}1420}14211422void TR::CompilationInfo::releaseCompilationLock()1423{1424if (_compilationMonitor)1425{1426debugPrint("\t\texternal user releasing compilatoin monitor\n");1427releaseCompMonitor(0);1428}1429}14301431TR::Monitor * TR::CompilationInfo::createLogMonitor()1432{1433_logMonitor = TR::Monitor::create("JIT-LogMonitor");1434return _logMonitor;1435}14361437void TR::CompilationInfo::acquireLogMonitor()1438{1439if (_logMonitor)1440{1441_logMonitor->enter();1442}1443}14441445void TR::CompilationInfo::releaseLogMonitor()1446{1447if ( _logMonitor)1448{1449_logMonitor->exit();1450}1451}14521453uint32_t1454TR::CompilationInfo::getMethodBytecodeSize(const J9ROMMethod * romMethod)1455{1456return (romMethod->bytecodeSizeHigh << 16) + romMethod->bytecodeSizeLow;1457}14581459#if defined(J9VM_OPT_JITSERVER)1460JITServer::ServerStream *1461TR::CompilationInfo::getStream()1462{1463return (TR::compInfoPT) ? TR::compInfoPT->getStream() : NULL;1464}1465#endif /* defined(J9VM_OPT_JITSERVER) */14661467uint32_t1468TR::CompilationInfo::getMethodBytecodeSize(J9Method* method)1469{1470#if defined(J9VM_OPT_JITSERVER)1471if (auto stream = TR::CompilationInfo::getStream())1472{1473{1474ClientSessionData *clientSessionData = TR::compInfoPT->getClientData();1475OMR::CriticalSection getRemoteROMClass(clientSessionData->getROMMapMonitor());1476auto it = clientSessionData->getJ9MethodMap().find(method);1477if (it != clientSessionData->getJ9MethodMap().end())1478{1479return getMethodBytecodeSize(it->second._romMethod);1480}1481}1482stream->write(JITServer::MessageType::CompInfo_getMethodBytecodeSize, method);1483return std::get<0>(stream->read<uint32_t>());1484}1485#endif /* defined(J9VM_OPT_JITSERVER) */1486return getMethodBytecodeSize(J9_ROM_METHOD_FROM_RAM_METHOD(method));1487}14881489bool1490TR::CompilationInfo::isJSR292(const J9ROMMethod *romMethod)1491{1492return (_J9ROMMETHOD_J9MODIFIER_IS_SET(romMethod, J9AccMethodHasMethodHandleInvokes));1493}14941495bool1496TR::CompilationInfo::isJSR292(J9Method *j9method)1497{1498#if defined(J9VM_OPT_JITSERVER)1499if (auto stream = TR::CompilationInfo::getStream())1500{1501{1502ClientSessionData *clientSessionData = TR::compInfoPT->getClientData();1503OMR::CriticalSection getRemoteROMClass(clientSessionData->getROMMapMonitor());1504auto it = clientSessionData->getJ9MethodMap().find(j9method);1505if (it != clientSessionData->getJ9MethodMap().end())1506{1507return isJSR292(it->second._romMethod);1508}1509}1510stream->write(JITServer::MessageType::CompInfo_isJSR292, j9method);1511return std::get<0>(stream->read<bool>());1512}1513#endif /* defined(J9VM_OPT_JITSERVER) */1514return isJSR292(J9_ROM_METHOD_FROM_RAM_METHOD(j9method));1515}15161517#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))1518void1519TR::CompilationInfo::disableAOTCompilations()1520{1521TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT, true);1522TR_DataCacheManager::getManager()->startupOver();1523}1524#endif15251526// Print the entire qualified name of the given method to the vlog1527// Caller must acquire vlog mutex1528//1529void TR::CompilationInfo::printMethodNameToVlog(J9Method *method)1530{1531J9UTF8 *className;1532J9UTF8 *name;1533J9UTF8 *signature;1534getClassNameSignatureFromMethod(method, className, name, signature);1535TR_VerboseLog::write("%.*s.%.*s%.*s", J9UTF8_LENGTH(className), (char *) J9UTF8_DATA(className),1536J9UTF8_LENGTH(name), (char *) J9UTF8_DATA(name),1537J9UTF8_LENGTH(signature), (char *) J9UTF8_DATA(signature));1538}15391540void TR::CompilationInfo::printMethodNameToVlog(const J9ROMClass* romClass, const J9ROMMethod* romMethod)1541{1542J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClass);1543J9UTF8 * name = J9ROMMETHOD_NAME(romMethod);1544J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(romMethod);1545TR_VerboseLog::write("%.*s.%.*s%.*s", J9UTF8_LENGTH(className), (char *)J9UTF8_DATA(className),1546J9UTF8_LENGTH(name), (char *)J9UTF8_DATA(name),1547J9UTF8_LENGTH(signature), (char *)J9UTF8_DATA(signature));1548}15491550//----------------------- Must hide these in TR::CompilationInfo ------1551#include "env/CpuUtilization.hpp"1552#include "infra/Statistics.hpp"1553#undef STATS1554#ifdef STATS1555TR_Stats statBudgetEpoch("Budget len at begining of epoch");1556TR_Stats statBudgetSmallLag("Budget/comp when smallLag");1557TR_Stats statBudgetMediumLag("Budget/comp when mediumLag");1558TR_Stats statEpochLength("Epoch lengh (ms)");1559char *eventNames[]={"SyncReq", "SmallLag", "LargeLag", "Medium-NoBudget", "Medium-highBudget", "Medium-LowBudget", "Medium-Idle"};1560TR_StatsEvents<7> statEvents("Scenarios", eventNames, 0);1561char *priorityName[]={"High","Normal"};1562TR_StatsEvents<2> statLowPriority("Medium-lowBudget-priority",priorityName,0);1563TR_Stats statLowBudget("Medium-lowBudget-budget");1564TR_Stats statQueueSize("Size of Compilation queue");1565TR_Stats statOverhead("Overhead of dynamicThreadPriority in cycles");1566#endif156715681569//---------------------- getCompilationLag --------------------------------1570// Looks at 2 things: size of method queue and the waiting time for the1571// current request to be processed.1572// Returns a compDelay code: LARGE_LAG, MEDIUM_LAG, SMALL_LAG1573//--------------------------------------------------------------------------1574int32_t TR::CompilationInfo::getCompilationLag()1575{1576if (getMethodQueueSize() > TR::CompilationInfo::LARGE_QUEUE)1577return TR::CompilationInfo::LARGE_LAG;15781579if (getMethodQueueSize() < TR::CompilationInfo::SMALL_QUEUE)1580return TR::CompilationInfo::SMALL_LAG;15811582return TR::CompilationInfo::MEDIUM_LAG;1583}15841585//------------------------ changeCompThreadPriority ------------------1586int32_t TR::CompilationInfoPerThread::changeCompThreadPriority(int32_t newPriority, int32_t locationCode)1587{1588// once in a while test that _compThreadPriority is OK;1589// we need this because the code is not thread safe15901591static uint32_t numInvocations = 0;1592if (((++numInvocations) & 0xf) == 0)1593{1594_compThreadPriority = j9thread_get_priority(getOsThread());1595}1596int32_t oldPriority = _compThreadPriority;1597// FIXME: minimize multithreading issues1598if (oldPriority != newPriority)1599{1600j9thread_set_priority(getOsThread(), newPriority);1601_compThreadPriority = newPriority;1602_compInfo._statNumPriorityChanges++;1603#ifdef STATS1604fprintf(stderr, "Changed priority to %d, location=%d\n", newPriority, locationCode);1605#endif1606}16071608return oldPriority;1609}16101611//------------------------ dynamicThreadPriority -------------------1612bool TR::CompilationInfo::dynamicThreadPriority()1613{1614static bool answer = TR::Options::getCmdLineOptions()->getOption(TR_DynamicThreadPriority) &&1615asynchronousCompilation() && TR::Compiler->target.numberOfProcessors() < 4;1616return answer;1617}161816191620// Needs compilation monitor in hand1621//----------------------------- enqueueCompReqToLPQ ------------------------1622void TR_LowPriorityCompQueue::enqueueCompReqToLPQ(TR_MethodToBeCompiled *compReq)1623{1624// add at the end of queue1625if (_lastLPQentry)1626_lastLPQentry->_next = compReq;1627else1628_firstLPQentry = compReq;16291630_lastLPQentry = compReq;1631_sizeLPQ++; // increase the size of LPQ1632increaseLPQWeightBy(compReq->_weight);1633}16341635//---------------------------- createLowPriorityCompReqAndQueueIt ---------------------1636bool TR_LowPriorityCompQueue::createLowPriorityCompReqAndQueueIt(TR::IlGeneratorMethodDetails &details, void *startPC, uint8_t reason)1637{1638TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(warm); // TODO: pick first opt level1639if (!plan)1640return false; // OOM16411642TR_MethodToBeCompiled * compReq = _compInfo->getCompilationQueueEntry();1643if (!compReq)1644{1645TR_OptimizationPlan::freeOptimizationPlan(plan);1646return false; // OOM1647}1648compReq->initialize(details, 0, CP_ASYNC_ABOVE_MIN, plan);1649compReq->_reqFromSecondaryQueue = reason;1650compReq->_jitStateWhenQueued = _compInfo->getPersistentInfo()->getJitState();1651compReq->_oldStartPC = startPC;1652compReq->_async = true; // app threads are not waiting for it1653165416551656// Determine entry weight1657J9Method *j9method = details.getMethod();1658J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(j9method);1659compReq->_weight = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod)) ? TR::CompilationInfo::WARM_LOOPY_WEIGHT : TR::CompilationInfo::WARM_LOOPLESS_WEIGHT;1660// add at the end of queue1661enqueueCompReqToLPQ(compReq);1662incStatsReqQueuedToLPQ(reason);1663return true;1664}16651666//------------------------ addFirstTimeReqToLPQ ---------------------1667bool TR_LowPriorityCompQueue::addFirstTimeCompReqToLPQ(J9Method *j9method, uint8_t reason)1668{1669if (TR::CompilationInfo::isCompiled(j9method))1670return false;1671TR::IlGeneratorMethodDetails details(j9method);1672return createLowPriorityCompReqAndQueueIt(details, NULL, reason);1673}167416751676//------------------------ addUpgradeReqToLPQ ----------------------1677// This method is used when the JIT performs a low optimized compilation1678// and then schedules a low priority upgrade compilation for the same method1679//------------------------------------------------------------------1680bool TR_LowPriorityCompQueue::addUpgradeReqToLPQ(TR_MethodToBeCompiled *compReq, uint8_t reason)1681{1682TR_ASSERT(!compReq->getMethodDetails().isNewInstanceThunk(), "classForNewInstance is sync req");1683// filter out DLT compilations and fixed opt level situations1684if (compReq->isDLTCompile() || !TR::Options::getCmdLineOptions()->allowRecompilation())1685return false;1686return createLowPriorityCompReqAndQueueIt(compReq->getMethodDetails(), compReq->_newStartPC, reason);1687}16881689bool TR::CompilationInfo::canProcessLowPriorityRequest()1690{1691// To avoid overhead cycling through all the threads, we should first1692// check if there is anything in that low priority queue1693//1694if (!getLowPriorityCompQueue().hasLowPriorityRequest()) // access _firstLPQentry without monitor in hand1695return false;16961697// If the main compilation queue has requests, we should serve those first1698if (getMethodQueueSize() != 0)1699return false;17001701#if defined(J9VM_OPT_JITSERVER)1702// If the first LPQ entry is REASON_SERVER_UNAVAILABLE, only attempt compilation if server is available by now1703if (getLowPriorityCompQueue().getFirstLPQRequest()->_reqFromSecondaryQueue == TR_MethodToBeCompiled::REASON_SERVER_UNAVAILABLE)1704return JITServerHelpers::isServerAvailable();1705#endif17061707// To process a request from the low priority queue we need to have1708// (1) no other compilation in progress (not required if TR_ConcurrentLPQ is enabled)1709// (2) some idle CPU1710// (3) current JVM not taking its entire share of CPU entitlement1711//1712if (TR::Options::getCmdLineOptions()->getOption(TR_ConcurrentLPQ) &&1713_jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP) // ConcurrentLPQ is too damaging to startup1714{1715if ((getCpuUtil() && getCpuUtil()->isFunctional() &&1716getCpuUtil()->getAvgCpuIdle() > idleThreshold() && // enough idle time1717getJvmCpuEntitlement() - getCpuUtil()->getVmCpuUsage() >= 200)) // at least 2 cpus should be not utilized1718return true;1719// Fall through the next case where we allow LPQ if the JVM leaves 50% of a CPU1720// unutilized, but there should be nothing in the main queue1721}17221723// Cycle through all the compilation threads1724for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)1725{1726TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];1727TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");17281729if (curCompThreadInfoPT->getMethodBeingCompiled())1730return false;1731}1732return (getCpuUtil() && getCpuUtil()->isFunctional() &&1733getCpuUtil()->getAvgCpuIdle() > idleThreshold() && // enough idle time1734getJvmCpuEntitlement() - getCpuUtil()->getVmCpuUsage() > 50); // at least half a processor should be empty1735}17361737int64_t1738TR::CompilationInfo::getCpuTimeSpentInCompilation()1739{1740I_64 totalTime = 0;1741for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)1742{1743TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];1744TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");17451746totalTime += j9thread_get_cpu_time(curCompThreadInfoPT->getOsThread());1747}17481749return totalTime;1750}17511752int32_t1753TR::CompilationInfo::changeCompThreadPriority(int32_t priority, int32_t locationCode)1754{1755fprintf(stderr, "Look at this code again\n");1756return 0;1757}17581759176017611762//--------------------- SmoothCompilation ------------------1763// How to improve: move all this computation outside the monitor1764// Do not lower the priority when inside the monitor1765// Minimize the number of priority changes by histerezis1766//1767// TODO: Does any of the calls in here require VM access?1768//----------------------------------------------------------1769bool1770TR::CompilationInfo::SmoothCompilation(TR_MethodToBeCompiled *entry, int32_t *optLevelAdjustment)1771{1772bool shouldAddRequestToUpgradeQueue = false;17731774if (shouldDowngradeCompReq(entry))1775{1776*optLevelAdjustment = -1; // decrease opt level1777_statNumDowngradeInterpretedMethod++;1778if (TR::Options::getCmdLineOptions()->getOption(TR_UseLowPriorityQueueDuringCLP) && !entry->isJNINative())1779shouldAddRequestToUpgradeQueue = true;1780}1781else1782{1783*optLevelAdjustment = 0; // unchanged opt level (default)1784}17851786if (shouldAddRequestToUpgradeQueue && entry->getMethodDetails().isNewInstanceThunk())1787shouldAddRequestToUpgradeQueue = false;1788return shouldAddRequestToUpgradeQueue;1789}17901791int32_t TR::CompilationInfo::getCompBudget() const1792{1793return _compilationBudget * (int32_t)TR::Compiler->target.numberOfProcessors();1794}17951796void1797TR::CompilationInfo::decNumGCRReqestsQueued(TR_MethodToBeCompiled *entry)1798{1799if (entry->_GCRrequest) _numGCRQueued--;1800}18011802void1803TR::CompilationInfo::incNumGCRRequestsQueued(TR_MethodToBeCompiled *entry)1804{1805entry->_GCRrequest = true; _numGCRQueued++;1806}18071808void1809TR::CompilationInfo::decNumInvReqestsQueued(TR_MethodToBeCompiled *entry)1810{1811if (entry->_entryIsCountedAsInvRequest)1812{1813_numInvRequestsInCompQueue--;1814TR_ASSERT(_numInvRequestsInCompQueue >= 0, "_numInvRequestsInCompQueue is negative : %d", _numInvRequestsInCompQueue);1815}1816}18171818void1819TR::CompilationInfo::incNumInvRequestsQueued(TR_MethodToBeCompiled *entry)1820{1821entry->_entryIsCountedAsInvRequest = true; _numInvRequestsInCompQueue++;1822}18231824void1825TR::CompilationInfo::updateCompQueueAccountingOnDequeue(TR_MethodToBeCompiled *entry)1826{1827_numQueuedMethods--; // one less method in the queue1828decNumGCRReqestsQueued(entry);1829decNumInvReqestsQueued(entry);1830if (entry->getMethodDetails().isOrdinaryMethod() && entry->_oldStartPC==0)1831{1832_numQueuedFirstTimeCompilations--;1833TR_ASSERT(_numQueuedFirstTimeCompilations >= 0, "_numQueuedFirstTimeCompilations is negative : %d", _numQueuedFirstTimeCompilations);1834}1835// Note: queue weight is handled separately because a method that is currently being1836// compiled is considered as bringing some weight to the processing backlog1837}183818391840//----------------------- useOptLevelAdjustment ---------------------1841// This scheme will be used only on multiprocessors because it is1842// based on compilation request queue size. On uniprocessors this1843// queue is always very small because, as soon as a request is put in1844// the queue, the compilation thread (working at MAX priority) will1845// occupy the CPU until compilation finishes1846//-------------------------------------------------------------------1847bool TR::CompilationInfo::useOptLevelAdjustment()1848{1849static bool answer = TR::Options::getCmdLineOptions()->getOption(TR_UseOptLevelAdjustment) &&1850asynchronousCompilation() &&1851TR::Options::getCmdLineOptions()->allowRecompilation();1852return answer;1853}185418551856// Must have compilation monitor in hand when calling this function1857void TR::CompilationInfo::invalidateRequestsForNativeMethods(J9Class * clazz, J9VMThread * vmThread)1858{1859bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);1860if (verbose)1861TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "invalidateRequestsForNativeMethods class=%p vmThread=%p", clazz, vmThread);18621863// Cycle through all the compilation threads1864for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)1865{1866TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];1867TR_MethodToBeCompiled *methodBeingCompiled = curCompThreadInfoPT->getMethodBeingCompiled();1868// Mark the method being compiled that it has been unloaded.1869// If it is already marked, then there is nothing to do.1870//1871if (methodBeingCompiled && !methodBeingCompiled->_unloadedMethod)1872{1873J9Method *method = methodBeingCompiled->getMethodDetails().getMethod();1874if (method)1875{1876J9Class *classOfMethod = J9_CLASS_FROM_METHOD(method);1877if (classOfMethod == clazz && TR::CompilationInfo::isJNINative(method))1878{1879// fail this compilation1880if (methodBeingCompiled->_priority < CP_SYNC_MIN) // ASYNC compilation, typical case1881{1882TR_ASSERT(methodBeingCompiled->_numThreadsWaiting == 0, "Async compilations should not have threads waiting");1883methodBeingCompiled->_newStartPC = 0;1884}1885else1886{1887methodBeingCompiled->acquireSlotMonitor(vmThread); // get queue-slot monitor1888methodBeingCompiled->_newStartPC = 0;1889methodBeingCompiled->getMonitor()->notifyAll(); // notify the waiting thread1890methodBeingCompiled->releaseSlotMonitor(vmThread); // release queue-slot monitor1891}1892methodBeingCompiled->_unloadedMethod = true;1893if (verbose)1894TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Have marked as unloaded the JNI thunk compilation for method %p", method);1895}1896}1897}1898} // end for18991900// if compiling on app thread, there is no compilation queue1901TR_MethodToBeCompiled *cur = _methodQueue;1902TR_MethodToBeCompiled *prev = NULL;1903while (cur)1904{1905TR_MethodToBeCompiled *next = cur->_next;1906J9Method *method = cur->getMethodDetails().getMethod();1907if (method &&1908J9_CLASS_FROM_METHOD(method) == clazz &&1909TR::CompilationInfo::isJNINative(method))1910{1911if (verbose)1912TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Invalidating JNI thunk compile request for method %p class %p", method, J9_CLASS_FROM_METHOD(method));1913if (cur->_priority >= CP_SYNC_MIN)1914{1915// squash this compilation request but inform waiting threads1916cur->acquireSlotMonitor(vmThread); // get queue-slot monitor1917cur->_newStartPC = 0;1918cur->getMonitor()->notifyAll(); // notify the waiting thread1919cur->releaseSlotMonitor(vmThread); // release queue-slot monitor1920}1921else1922{1923TR_ASSERT(cur->_numThreadsWaiting == 0, "Async compilations should not have threads waiting");1924}19251926// detach from queue1927if (prev)1928prev->_next = cur->_next;1929else1930_methodQueue = cur->_next;1931updateCompQueueAccountingOnDequeue(cur);1932// decrease the queue weight1933decreaseQueueWeightBy(cur->_weight);1934// put back into the pool1935recycleCompilationEntry(cur);1936}1937else1938{1939prev = cur;1940}1941cur = next;1942}1943// LPQ does not need to be checked because JNI thunk requests cannot be put in LPQ1944}19451946void TR::CompilationInfo::invalidateRequestsForUnloadedMethods(TR_OpaqueClassBlock * clazz, J9VMThread * vmThread, bool hotCodeReplacement)1947{1948TR_J9VMBase * fe = TR_J9VMBase::get(_jitConfig, vmThread);1949J9Class *unloadedClass = clazz ? TR::Compiler->cls.convertClassOffsetToClassPtr(clazz) : NULL;1950bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);1951if (verbose)1952TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "invalidateRequestsForUnloadedMethods class=%p vmThread=%p hotCodeReplacement=%d", clazz, vmThread, hotCodeReplacement);19531954for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)1955{1956TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];1957TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");19581959TR_MethodToBeCompiled *methodBeingCompiled = curCompThreadInfoPT->getMethodBeingCompiled();1960// Mark the method being compiled that it has been unloaded.1961// If it is already marked, then there is nothing to do.1962//1963if (methodBeingCompiled && !methodBeingCompiled->_unloadedMethod)1964{1965TR::IlGeneratorMethodDetails &details = methodBeingCompiled->getMethodDetails();1966J9Method *method = details.getMethod();1967TR_ASSERT(method, "_method can be NULL only at shutdown time");1968if ((!unloadedClass && hotCodeReplacement) || // replacement in FSD mode1969J9_CLASS_FROM_METHOD(method) == unloadedClass ||1970(details.isNewInstanceThunk() &&1971static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))1972{1973if (!hotCodeReplacement)1974{1975TR_ASSERT(methodBeingCompiled->_priority < CP_SYNC_MIN,1976"Unloading cannot happen for SYNC requests");1977}1978else1979{1980TR_ASSERT(methodBeingCompiled->_numThreadsWaiting == 0 || methodBeingCompiled->_priority >= CP_SYNC_MIN,1981"threads can be waiting only for sync compilations");1982if (methodBeingCompiled->_priority >= CP_SYNC_MIN)1983{1984// fail this compilation1985methodBeingCompiled->acquireSlotMonitor(vmThread); // get queue-slot monitor1986methodBeingCompiled->_newStartPC = 0;1987methodBeingCompiled->getMonitor()->notifyAll(); // notify the waiting thread1988methodBeingCompiled->releaseSlotMonitor(vmThread); // release queue-slot monitor1989}1990}1991methodBeingCompiled->_unloadedMethod = true;1992}1993}1994} // end for1995// if compiling on app thread, there is no compilation queue1996TR_MethodToBeCompiled *cur = _methodQueue;1997TR_MethodToBeCompiled *prev = NULL;1998bool verboseDetails = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails);1999while (cur)2000{2001TR_MethodToBeCompiled *next = cur->_next;2002TR::IlGeneratorMethodDetails &details = cur->getMethodDetails();2003J9Method *method = details.getMethod();2004//TR_ASSERT(details.getMethod(), "method can be NULL only at shutdown time");2005// ^^^ bad assume: shutdown and class unload CAN happen at the same time.2006if (method)2007{2008J9Class *methodClass = J9_CLASS_FROM_METHOD(method);2009if (verboseDetails)2010TR_VerboseLog::writeLineLocked(TR_Vlog_HD,"Looking at compile request for method %p class %p", method, methodClass);2011if ((!unloadedClass && hotCodeReplacement) || // replacement in FSD mode2012methodClass == unloadedClass ||2013(details.isNewInstanceThunk() &&2014static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))2015{2016if (verbose)2017TR_VerboseLog::writeLineLocked(TR_Vlog_HK,"Invalidating compile request for method %p class %p", method, methodClass);2018if (!hotCodeReplacement)2019{2020TR_ASSERT(cur->_priority < CP_SYNC_MIN,2021"Unloading cannot happen for SYNC requests");2022}2023else2024{2025TR_ASSERT(cur->_numThreadsWaiting == 0 || cur->_priority >= CP_SYNC_MIN,2026"threads can be waiting only for sync compilations");2027// if this method is synchronous we need to signal the waiting thread2028if (cur->_priority >= CP_SYNC_MIN)2029{2030// fail this compilation2031cur->acquireSlotMonitor(vmThread); // get queue-slot monitor2032cur->_newStartPC = 0;2033cur->getMonitor()->notifyAll(); // notify the waiting thread2034cur->releaseSlotMonitor(vmThread); // release queue-slot monitor2035}2036}2037// detach from queue2038if (prev)2039prev->_next = cur->_next;2040else2041_methodQueue = cur->_next;2042updateCompQueueAccountingOnDequeue(cur);2043// decrease the queue weight2044decreaseQueueWeightBy(cur->_weight);2045// put back into the pool2046recycleCompilationEntry(cur);2047}2048else2049{2050prev = cur;2051}2052}2053else2054{2055prev = cur;2056}2057cur = next;2058}20592060// process the low priority queue as well2061getLowPriorityCompQueue().invalidateRequestsForUnloadedMethods(unloadedClass);2062// and JProfiling queue ...2063getJProfilingCompQueue().invalidateRequestsForUnloadedMethods(unloadedClass);2064}20652066// Helper to determine if compilation needs to be aborted due to class unloading2067// or hot code replacement2068// Side-effects: may change entry->_compErrorCode2069bool TR::CompilationInfo::shouldAbortCompilation(TR_MethodToBeCompiled *entry, TR::PersistentInfo *persistentInfo)2070{2071if (entry->isOutOfProcessCompReq())2072return false; // will abort at the client20732074if (entry->_unloadedMethod) // method was unloaded while we were trying to compile it2075{2076TR_ASSERT(entry->_compErrCode == compilationInterrupted, "Received error code %u, expect compilationInterrupted when the method was unloaded", entry->_compErrCode);2077entry->_compErrCode = compilationNotNeeded; // change error code2078return true;2079}2080if ((TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR) || TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug)))2081{2082TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();2083J9Class *clazz = details.getClass();2084if (clazz && J9_IS_CLASS_OBSOLETE(clazz))2085{2086TR_ASSERT(0, "Should never have compiled replaced method %p", details.getMethod());2087entry->_compErrCode = compilationKilledByClassReplacement;2088return true;2089}2090}2091return false;2092}20932094// This method has side-effects, It modifies the optimization plan and persistentMethodInfo2095// This method is executed with compilationMonitor in hand2096//2097bool TR::CompilationInfo::shouldRetryCompilation(TR_MethodToBeCompiled *entry, TR::Compilation *comp)2098{2099// The JITServer should not retry compilations on it's own,2100// it should let the client make that decision2101if (entry->isOutOfProcessCompReq())2102return false;21032104bool tryCompilingAgain = false;2105TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();2106J9Method *method = details.getMethod();21072108// when the compilation fails we might retry2109//2110if (entry->_compErrCode != compilationOK)2111{2112if (entry->_compilationAttemptsLeft > 0)2113{21142115TR_PersistentJittedBodyInfo *bodyInfo;2116switch (entry->_compErrCode)2117{2118case compilationAotValidateFieldFailure:2119case compilationAotStaticFieldReloFailure:2120case compilationAotClassReloFailure:2121case compilationAotThunkReloFailure:2122case compilationAotHasInvokehandle:2123case compilationAotHasInvokeVarHandle:2124case compilationAotPatchedCPConstant:2125case compilationAotHasInvokeSpecialInterface:2126case compilationAotValidateMethodExitFailure:2127case compilationAotValidateMethodEnterFailure:2128case compilationAotClassChainPersistenceFailure:2129case compilationAotValidateStringCompressionFailure:2130case compilationSymbolValidationManagerFailure:2131case compilationAOTNoSupportForAOTFailure:2132case compilationAOTValidateTMFailure:2133case compilationAOTRelocationRecordGenerationFailure:2134case compilationAotValidateExceptionHookFailure:2135case compilationAotBlockFrequencyReloFailure:2136case compilationAotRecompQueuedFlagReloFailure:2137case compilationAOTValidateOSRFailure:2138// switch to JIT for these cases (we don't want to relocate again)2139entry->_doNotUseAotCodeFromSharedCache = true;2140tryCompilingAgain = true;2141break;2142//case compilationAotRelocationFailure:2143case compilationAotTrampolineReloFailure:2144case compilationAotPicTrampolineReloFailure:2145case compilationAotCacheFullReloFailure:2146// for the last one, switch to JIT2147if (entry->_compilationAttemptsLeft == 1)2148entry->_doNotUseAotCodeFromSharedCache = true;2149tryCompilingAgain = true;2150break;2151#if defined(J9VM_OPT_JITSERVER)2152case compilationStreamFailure:2153// if -XX:+JITServerRequireServer is used, we would like the client to fail when server crashes2154if (entry->_compInfoPT->getCompilationInfo()->getPersistentInfo()->getRequireJITServer())2155{2156TR_ASSERT_FATAL(false, "Option -XX:+JITServerRequireServer is used, terminate the JITClient due to unavailable JITServer.");2157}2158case compilationStreamMessageTypeMismatch:2159case compilationStreamVersionIncompatible:2160case compilationStreamLostMessage:2161case aotCacheDeserializationFailure:2162#endif2163case compilationInterrupted:2164case compilationCodeReservationFailure:2165case compilationRecoverableTrampolineFailure:2166case compilationIllegalCodeCacheSwitch:2167case compilationRecoverableCodeCacheError:2168tryCompilingAgain = true;2169break;2170case compilationExcessiveComplexity:2171case compilationHeapLimitExceeded:2172case compilationLowPhysicalMemory:2173case compilationInternalPointerExceedLimit:2174case compilationVirtualAddressExhaustion:2175if (comp->getOption(TR_Timing))2176{2177comp->phaseTimer().DumpSummary(*comp);2178}21792180if (comp->getOption(TR_LexicalMemProfiler))2181{2182comp->phaseMemProfiler().DumpSummary(*comp);2183}21842185if (!((TR_J9VMBase *)comp->fej9())->isAOT_DEPRECATED_DO_NOT_USE())2186{2187TR_J9SharedCache *sc = (TR_J9SharedCache *) (((TR_J9VMBase *)comp->fej9())->sharedCache());2188if (sc)2189{2190switch (entry->_optimizationPlan->getOptLevel())2191{2192case cold:2193case warm:2194sc->addHint(method, TR_HintFailedWarm);2195break;2196case hot:2197sc->addHint(method, TR_HintFailedHot);2198break;2199case scorching:2200case veryHot:2201sc->addHint(method, TR_HintFailedScorching);2202break;2203default:2204break;2205}2206}2207}22082209bodyInfo = 0;2210if (comp->allowRecompilation() && entry->_optimizationPlan && entry->_optimizationPlan->getOptLevel() > minHotness)2211{2212// Compile only if the method is interpreted or if it's compiled with2213// profiling information.2214if (entry->_oldStartPC == 0) // interpreter method2215{2216tryCompilingAgain = true;2217}2218else // Does the existing body contain profiling info?2219{2220bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(entry->_oldStartPC);2221if (bodyInfo->getIsProfilingBody())2222tryCompilingAgain = true;2223// if existing body is invalidated, retry the compilation2224else if (bodyInfo->getIsInvalidated())2225tryCompilingAgain = true;2226// if the existing body uses pre-existence, retry the compilation2227// otherwise we will revert to interpreted when failing this compilation2228else if (bodyInfo->getUsesPreexistence())2229tryCompilingAgain = true;2230}2231}22322233if (tryCompilingAgain)2234{2235TR_Hotness hotness = entry->_optimizationPlan->getOptLevel();2236TR_Hotness newHotness;2237if (hotness == veryHot)2238newHotness = warm; // skip over hot and go down two levels2239else if (hotness <= scorching)2240newHotness = (TR_Hotness)(hotness - 1);2241else // Why would we use hotness greater than scorching2242newHotness = noOpt;2243entry->_optimizationPlan->setOptLevel(newHotness);2244entry->_optimizationPlan->setInsertInstrumentation(false); // prevent profiling2245entry->_optimizationPlan->setUseSampling(false); // disable recompilation of this method2246entry->_optimizationPlan->setDisableEDO(true); // disable EDO to prevent recompilation triggered from native code2247entry->_optimizationPlan->setDisableGCR(true); // disable GCR to prevent recompilation triggered from native code2248}2249break;2250case compilationCHTableCommitFailure:2251tryCompilingAgain = true;2252// if we have only one more trial left, disable optimizations based on CHTable2253if (entry->_compilationAttemptsLeft == 1)2254entry->_optimizationPlan->setDisableCHOpts();2255break;2256case compilationNeededAtHigherLevel:2257if (comp->allowRecompilation() && (comp->getNextOptLevel()!=unknownHotness))2258{2259tryCompilingAgain = true;2260TR_Hotness newHotness = comp->getNextOptLevel();2261entry->_optimizationPlan->setOptLevel(newHotness);2262}2263break;22642265case compilationMaxCallerIndexExceeded:2266{2267tryCompilingAgain = true;2268// bump the factor that will indicate by how much to reduce the MAX_PEEKED_BYTECODE_SIZE2269uint32_t val = entry->_optimizationPlan->getReduceMaxPeekedBytecode();2270entry->_optimizationPlan->setReduceMaxPeekedBytecode(val+1);2271// if we have only one more trial left, make sure you don't try above warm opt level2272// Lookahead at warm is disabled by default2273if (entry->_compilationAttemptsLeft == 1)2274{2275TR_Hotness hotness = entry->_optimizationPlan->getOptLevel();2276TR_Hotness newHotness = hotness > warm ? warm : hotness;2277entry->_optimizationPlan->setOptLevel(newHotness);2278entry->_optimizationPlan->setInsertInstrumentation(false); // prevent profiling2279entry->_optimizationPlan->setUseSampling(false); // disable recompilation of this method2280// In the future we may have to disable OptServer as well2281}2282break;2283}2284case compilationGCRPatchFailure:2285// Disable GCR trees for this body2286entry->_optimizationPlan->setDisableGCR();2287tryCompilingAgain = true;2288break;2289case compilationLambdaEnforceScorching:2290// This must be a warm compilation. Retry the same compilation at scorching even if it's a first time compilation2291// Watch out for the following scenario: (1) warm comp req. (2) Ilgen fails comp because it wants a hot comp2292// (3) hot comp fails due to some compiler limit and we lower opt level at warm; (4) Ilgen fails again because2293// it wants a hot compilation2294// Also we should not fail the compilation for fixed opt level.2295if (entry->_compilationAttemptsLeft == MAX_COMPILE_ATTEMPTS) // Raise opt level only for the first attempt2296{2297TR_Hotness hotness = entry->_optimizationPlan->getOptLevel();2298if (hotness <= veryHot )2299{2300entry->_optimizationPlan->setOptLevel(scorching); // force scorching recompilation2301entry->_optimizationPlan->setDontFailOnPurpose(true);2302entry->_optimizationPlan->setDoNotSwitchToProfiling(true);2303entry->_optimizationPlan->setDisableGCR();2304tryCompilingAgain = true;2305// If we were doing an AOT warm compilation, we will refrain from doing an AOT-hot2306// because we do not allow AOT compilations as retrials2307// (see entry->_useAotCompilation = false; at the end of this method)2308// This is what we probably want2309}2310}2311break;2312case compilationEnforceProfiling:2313entry->_optimizationPlan->setInsertInstrumentation(true); // enable profiling2314entry->_optimizationPlan->setDoNotSwitchToProfiling(true); // don't allow another switch2315entry->_optimizationPlan->setDisableGCR(); // GCR isn't needed2316tryCompilingAgain = true;2317break;2318case compilationNullSubstituteCodeCache:2319case compilationCodeMemoryExhausted:2320case compilationCodeCacheError:2321case compilationDataCacheError:2322default:2323break;2324} // end switch2325if (tryCompilingAgain && comp)2326{2327TR_PersistentMethodInfo *methodInfo = TR_PersistentMethodInfo::get(comp);2328if (methodInfo)2329methodInfo->setNextCompileLevel(entry->_optimizationPlan->getOptLevel(), entry->_optimizationPlan->insertInstrumentation());2330}2331}2332else if (0) // later add test for multiple aot relocation failure to catch that scenario, which shouldn't happen2333{2334TR_ASSERT(0, "multiple aot relocations likely failed for same method");2335}2336}// if (entry->_compErrCode != compilationOK)23372338// don't carry the decision to generate AOT code to the next compilation2339// because it may no longer be the right thing to do at that point2340if (tryCompilingAgain)2341entry->_useAotCompilation = false;23422343return tryCompilingAgain;2344}23452346// if compiling on app thread, there is no compilation queue2347void TR::CompilationInfo::purgeMethodQueue(TR_CompilationErrorCode errorCode)2348{2349// Must enter _compilationMonitor before calling this2350J9JavaVM *vm = _jitConfig->javaVM;2351J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);2352// Generate a trace point2353Trc_JIT_purgeMethodQueue(vmThread);23542355while (_methodQueue)2356{2357TR_MethodToBeCompiled * cur = _methodQueue;2358_methodQueue = cur->_next;2359updateCompQueueAccountingOnDequeue(cur);2360// decrease the queue weight2361decreaseQueueWeightBy(cur->_weight);23622363// must wake up the working threads that are waiting for the2364// compilation to finish (only for sync comp req)2365// we also need to fail all those compilations23662367// Acquire the queue slot monitor now2368//2369debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");2370cur->acquireSlotMonitor(vmThread);2371debugPrint(vmThread, "+AM-", cur);23722373// fail the compilation2374void *startPC = 0;23752376startPC = compilationEnd(vmThread, cur->getMethodDetails(), _jitConfig, NULL, cur->_oldStartPC);2377cur->_newStartPC = startPC;2378cur->_compErrCode = errorCode;23792380// notify the sleeping threads2381//2382debugPrint(vmThread, "\tnotify sleeping threads that the compilation is done\n");2383cur->getMonitor()->notifyAll();2384debugPrint(vmThread, "ntfy-", cur);23852386// Release the queue slot monitor2387//2388debugPrint(vmThread, "\tcompilation thread releasing queue slot monitor\n");2389debugPrint(vmThread, "-AM-", cur);2390cur->releaseSlotMonitor(vmThread);23912392recycleCompilationEntry(cur);2393}23942395// delete all entries from the low priority queue2396getLowPriorityCompQueue().purgeLPQ();2397// and from JProfiling queue2398getJProfilingCompQueue().purge();2399}24002401void TR::CompilationInfoPerThread::suspendCompilationThread()2402{2403_compInfo.acquireCompMonitor(_compilationThread);24042405if (compilationThreadIsActive())2406{2407setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);24082409if (!isDiagnosticThread())2410getCompilationInfo()->decNumCompThreadsActive();24112412if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))2413{2414TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Suspension request for compThread %d sleeping=%s",2415(uint32_t)getCompilationInfo()->getPersistentInfo()->getElapsedTime(), getCompThreadId(), getMethodBeingCompiled()?"NO":"YES");2416}24172418// What happens if the thread is sleeping on the compilationQueueMonitor?2419if (getCompilationInfo()->getNumCompThreadsActive() == 0)2420getCompilationInfo()->purgeMethodQueue(compilationSuspended);2421}2422_compInfo.releaseCompMonitor(_compilationThread);2423// The thread will be sleeping on the compThreadMonitor whenever it finishes current compilation2424}24252426//-------------------------- suspendCompilationThread ------------------------2427// This method may be called when we want all JIT activity to stop temporarily2428// It is called normally by a java thread2429//----------------------------------------------------------------------------2430void TR::CompilationInfo::suspendCompilationThread()2431{2432// if we compile on application thread, there is no compilation2433// request queue and there is no compilation thread2434// There can only be one request that is in progress. All the others2435// will see the SUSPENDED state when they get the application monitor24362437TR_ASSERT(_compilationMonitor, "Must have a compilation queue monitor\n");2438J9JavaVM *vm = _jitConfig->javaVM;2439J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);2440if (!vmThread)2441return; // cannot do it without a vmThread FIXME: why?2442acquireCompMonitor(vmThread);24432444// Must visit all compilation threads2445bool stoppedOneCompilationThread = false;2446for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)2447{2448TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];2449TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");24502451// Only compilation threads that are active need to be suspended2452if (curCompThreadInfoPT->compilationThreadIsActive())2453{2454curCompThreadInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);2455decNumCompThreadsActive();2456// should we try to interrupt the compilation in progress?2457stoppedOneCompilationThread = true;2458if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))2459{2460TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Suspension request for compThread %d sleeping=%s",2461(uint32_t)getPersistentInfo()->getElapsedTime(), curCompThreadInfoPT->getCompThreadId(), curCompThreadInfoPT->getMethodBeingCompiled()?"NO":"YES");2462}2463}2464}2465if (stoppedOneCompilationThread)2466purgeMethodQueue(compilationSuspended);2467TR_ASSERT(_numCompThreadsActive == 0, "We must have all compilation threads suspended at this point\n");2468releaseCompMonitor(vmThread);2469}24702471void TR::CompilationInfoPerThread::resumeCompilationThread()2472{2473_compInfo.acquireCompMonitor(_compilationThread);24742475if (getCompilationThreadState() == COMPTHREAD_SUSPENDED ||2476getCompilationThreadState() == COMPTHREAD_SIGNAL_SUSPEND)2477{2478if (getCompilationThreadState() == COMPTHREAD_SUSPENDED)2479{2480setCompilationThreadState(COMPTHREAD_ACTIVE);2481getCompThreadMonitor()->enter();2482getCompThreadMonitor()->notifyAll(); // wake the suspended thread2483getCompThreadMonitor()->exit();2484}2485else // COMPTHREAD_SIGNAL_SUSPEND2486{2487setCompilationThreadState(COMPTHREAD_ACTIVE);2488}24892490// The diagnostic thread should not be counted as active2491if (!isDiagnosticThread())2492getCompilationInfo()->incNumCompThreadsActive();24932494if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))2495{2496TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Resume request for compThread %d",2497(uint32_t)getCompilationInfo()->getPersistentInfo()->getElapsedTime(), getCompThreadId());2498}2499}25002501_compInfo.releaseCompMonitor(_compilationThread);2502}25032504//----------------------------- resumeCompilationThread -----------------------2505// This version of resumeCompilationThread wakes up several compilation threads2506//-----------------------------------------------------------------------------2507void TR::CompilationInfo::resumeCompilationThread()2508{2509J9JavaVM *vm = _jitConfig->javaVM;2510J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);2511acquireCompMonitor(vmThread);25122513/*2514* Count active/suspended threads for sake of sanity.2515* We can afford to do it because this method is not invoked very often2516*2517* FIXME:2518* we are now using an array, so there is no linked list to count;2519* therefore, we might be able to remove this entirely2520*/2521int32_t numActiveCompThreads = 0; // RAS purposes2522int32_t numHot = 0;2523TR::CompilationInfoPerThread *compInfoPTHot = NULL;2524for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)2525{2526TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];2527TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");25282529CompilationThreadState currentThreadState = curCompThreadInfoPT->getCompilationThreadState();2530if (currentThreadState == COMPTHREAD_ACTIVE ||2531currentThreadState == COMPTHREAD_SIGNAL_WAIT ||2532currentThreadState == COMPTHREAD_WAITING ||2533currentThreadState == COMPTHREAD_SIGNAL_SUSPEND)2534{2535if (curCompThreadInfoPT->compilationThreadIsActive())2536numActiveCompThreads++;2537if (curCompThreadInfoPT->getMethodBeingCompiled() &&2538curCompThreadInfoPT->getMethodBeingCompiled()->_hasIncrementedNumCompThreadsCompilingHotterMethods)2539{2540numHot++;2541if (currentThreadState == COMPTHREAD_SIGNAL_SUSPEND)2542compInfoPTHot = curCompThreadInfoPT; // memorize this for later2543}2544}2545}25462547// Check that our view about the number of active compilation threads is correct2548//2549if (numActiveCompThreads != getNumCompThreadsActive())2550{2551TR_ASSERT(false, "Discrepancy regarding active compilation threads: numActiveCompThreads=%d getNumCompThreadsActive()=%d\n", numActiveCompThreads, getNumCompThreadsActive());2552setNumCompThreadsActive(numActiveCompThreads); // Apply correction2553}2554if (getNumCompThreadsCompilingHotterMethods() != numHot)2555{2556TR_ASSERT(false, "Inconsistency with hot threads %d %d\n", getNumCompThreadsCompilingHotterMethods(), numHot);2557setNumCompThreadsCompilingHotterMethods(numHot); // apply correction2558}25592560// If there is a compilation thread executing a hot compilation and the state is2561// SUSPENDING, activate this thread first (see defect 182392)2562if (compInfoPTHot)2563{2564compInfoPTHot->setCompilationThreadState(COMPTHREAD_ACTIVE);2565incNumCompThreadsActive();2566if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))2567{2568TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Resume compThread %d Qweight=%d active=%d",2569(uint32_t)getPersistentInfo()->getElapsedTime(),2570compInfoPTHot->getCompThreadId(),2571getQueueWeight(),2572getNumCompThreadsActive());2573}2574}25752576// If dynamicThreadActivation is used, wake compilation threads only as2577// many as required; otherwise wake them all2578for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)2579{2580TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];2581TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");25822583TR_YesNoMaybe activate = shouldActivateNewCompThread();2584if (activate == TR_no)2585break;25862587curCompThreadInfoPT->resumeCompilationThread();2588}25892590if (getNumCompThreadsActive() == 0)2591{2592TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "No threads were activated following a resume all compilation threads call");2593}25942595releaseCompMonitor(vmThread);2596}259725982599int TR::CompilationInfo::computeCompilationThreadPriority(J9JavaVM *vm)2600{2601int priority = J9THREAD_PRIORITY_USER_MAX; // default value26022603// convert priority codes into priorities defined by the VM2604static UDATA priorityConversionTable[]={J9THREAD_PRIORITY_MIN,2605J9THREAD_PRIORITY_USER_MIN,2606J9THREAD_PRIORITY_NORMAL,2607J9THREAD_PRIORITY_USER_MAX,2608J9THREAD_PRIORITY_MAX};2609if (TR::Options::_compilationThreadPriorityCode >= 0 &&2610TR::Options::_compilationThreadPriorityCode <= 4)2611priority = priorityConversionTable[TR::Options::_compilationThreadPriorityCode];2612return priority;2613}26142615TR::CompilationInfoPerThread* TR::CompilationInfo::getCompInfoForThread(J9VMThread *vmThread)2616{2617for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)2618{2619TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];2620TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");26212622if (vmThread == curCompThreadInfoPT->getCompilationThread())2623return curCompThreadInfoPT;2624}26252626return NULL;2627}26282629int32_t *TR::CompilationInfo::_compThreadActivationThresholds = NULL;2630int32_t *TR::CompilationInfo::_compThreadSuspensionThresholds = NULL;2631int32_t *TR::CompilationInfo::_compThreadActivationThresholdsonStarvation = NULL;26322633void TR::CompilationInfo::updateNumUsableCompThreads(int32_t &numUsableCompThreads)2634{2635#if defined(J9VM_OPT_JITSERVER)2636if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)2637{2638if (numUsableCompThreads <= 0)2639{2640numUsableCompThreads = DEFAULT_SERVER_USABLE_COMP_THREADS;2641}2642else if (numUsableCompThreads > MAX_SERVER_USABLE_COMP_THREADS)2643{2644fprintf(stderr,2645"Requested number of compilation threads is over the limit of %u.\n"2646"Will use the default number of threads: %u.\n",2647MAX_SERVER_USABLE_COMP_THREADS, DEFAULT_SERVER_USABLE_COMP_THREADS2648);2649numUsableCompThreads = DEFAULT_SERVER_USABLE_COMP_THREADS;2650}2651}2652else2653#endif /* defined(J9VM_OPT_JITSERVER) */2654{2655if (numUsableCompThreads <= 0)2656{2657numUsableCompThreads = DEFAULT_CLIENT_USABLE_COMP_THREADS;2658}2659else if (numUsableCompThreads > MAX_CLIENT_USABLE_COMP_THREADS)2660{2661fprintf(stderr,2662"Requested number of compilation threads is over the limit of %u. Will use %u threads.\n",2663MAX_CLIENT_USABLE_COMP_THREADS, MAX_CLIENT_USABLE_COMP_THREADS2664);2665numUsableCompThreads = MAX_CLIENT_USABLE_COMP_THREADS;2666}2667}2668}26692670bool2671TR::CompilationInfo::allocateCompilationThreads(int32_t numUsableCompThreads)2672{2673if (_compThreadActivationThresholds ||2674_compThreadSuspensionThresholds ||2675_compThreadActivationThresholdsonStarvation ||2676_arrayOfCompilationInfoPerThread)2677{2678TR_ASSERT_FATAL(false, "Compilation threads have been allocated\n");2679return false;2680}26812682TR_ASSERT((numUsableCompThreads == TR::Options::_numUsableCompilationThreads),2683"numUsableCompThreads %d is not equal to the Option value %d", numUsableCompThreads, TR::Options::_numUsableCompilationThreads);26842685#if defined(J9VM_OPT_JITSERVER)2686if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)2687{2688TR_ASSERT((0 < numUsableCompThreads) && (numUsableCompThreads <= MAX_SERVER_USABLE_COMP_THREADS),2689"numUsableCompThreads %d is greater than supported %d", numUsableCompThreads, MAX_SERVER_USABLE_COMP_THREADS);2690}2691else2692#endif /* defined(J9VM_OPT_JITSERVER) */2693{2694TR_ASSERT((0 < numUsableCompThreads) && (numUsableCompThreads <= MAX_CLIENT_USABLE_COMP_THREADS),2695"numUsableCompThreads %d is greater than supported %d", numUsableCompThreads, MAX_CLIENT_USABLE_COMP_THREADS);2696}26972698uint32_t numTotalCompThreads = numUsableCompThreads + MAX_DIAGNOSTIC_COMP_THREADS;26992700TR::MonitorTable *table = TR::MonitorTable::get();2701if ((!table) ||2702(!table->allocInitClassUnloadMonitorHolders(numTotalCompThreads)))2703{2704return false;2705}27062707_compThreadActivationThresholds = static_cast<int32_t *>(jitPersistentAlloc((numTotalCompThreads + 1) * sizeof(int32_t)));2708_compThreadSuspensionThresholds = static_cast<int32_t *>(jitPersistentAlloc((numTotalCompThreads + 1) * sizeof(int32_t)));2709_compThreadActivationThresholdsonStarvation = static_cast<int32_t *>(jitPersistentAlloc((numTotalCompThreads + 1) * sizeof(int32_t)));27102711_arrayOfCompilationInfoPerThread = static_cast<TR::CompilationInfoPerThread **>(jitPersistentAlloc(numTotalCompThreads * sizeof(TR::CompilationInfoPerThread *)));27122713if (_compThreadActivationThresholds &&2714_compThreadSuspensionThresholds &&2715_compThreadActivationThresholdsonStarvation &&2716_arrayOfCompilationInfoPerThread)2717{2718// How to read it: the queueWeight has to be over 100 to activate second comp thread2719// the queueWeight has to be below 10 to suspend second comp thread2720// For example:2721// compThreadActivationThresholds[MAX_TOTAL_COMP_THREADS+1] = {-1, 100, 200, 300, 400, 500, 600, 700, 800};2722// compThreadSuspensionThresholds[MAX_TOTAL_COMP_THREADS+1] = {-1, -1, 10, 110, 210, 310, 410, 510, 610};2723// compThreadActivationThresholdsonStarvation[MAX_TOTAL_COMP_THREADS+1] = {-1, 800, 1600, 3200, 6400, 12800, 19200, 25600, 32000};2724_compThreadActivationThresholds[0] = -1;2725_compThreadActivationThresholds[1] = 100;2726_compThreadActivationThresholds[2] = 200;27272728_compThreadSuspensionThresholds[0] = -1;2729_compThreadSuspensionThresholds[1] = -1;2730_compThreadSuspensionThresholds[2] = 10;27312732for (int32_t i=3; i<(numTotalCompThreads+1); ++i)2733{2734_compThreadActivationThresholds[i] = _compThreadActivationThresholds[i-1] + 100;2735_compThreadSuspensionThresholds[i] = _compThreadSuspensionThresholds[i-1] + 100;2736}27372738_compThreadActivationThresholdsonStarvation[0] = -1;2739_compThreadActivationThresholdsonStarvation[1] = 800;27402741for (int32_t i=2; i<(numTotalCompThreads+1); ++i)2742{2743if (_compThreadActivationThresholdsonStarvation[i-1] < 12800)2744{2745_compThreadActivationThresholdsonStarvation[i] = _compThreadActivationThresholdsonStarvation[i-1] * 2;2746}2747else2748{2749_compThreadActivationThresholdsonStarvation[i] = _compThreadActivationThresholdsonStarvation[i-1] + 6400;2750}2751}27522753for (int32_t i=0; i<numTotalCompThreads; ++i)2754{2755_arrayOfCompilationInfoPerThread[i] = NULL;2756}2757return true;2758}2759return false;2760}27612762//-------------------------- startCompilationThread --------------------------2763// Start ONE compilation thread and initialize the associated2764// TR::CompilationInfoPerThread structure2765// This function returns immediately after the thread is created2766// Parameters:2767// priority - the desired priority of the thread (0..5); negative number2768// means that the priority will be computed automatically2769// Return value: 0 for success; error code for any error2770//----------------------------------------------------------------------------2771uintptr_t2772TR::CompilationInfo::startCompilationThread(int32_t priority, int32_t threadId, bool isDiagnosticThread)2773{2774if (!_compilationMonitor)2775return 1;27762777if (!isDiagnosticThread)2778{2779if (_numCompThreads >= TR::Options::_numUsableCompilationThreads)2780return 1;2781}2782else2783{2784if (_numDiagnosticThreads >= MAX_DIAGNOSTIC_COMP_THREADS)2785return 1;27862787// _compInfoForDiagnosticCompilationThread should be NULL before creation2788if (_compInfoForDiagnosticCompilationThread)2789return 1;2790}27912792J9JavaVM * vm = jitConfig->javaVM;2793PORT_ACCESS_FROM_JAVAVM(vm);27942795setCompBudget(TR::Options::_compilationBudget); // might do it several time, but it does not hurt27962797// Create a compInfo for this thread2798#if defined(J9VM_OPT_JITSERVER)2799TR::CompilationInfoPerThread *compInfoPT = getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER ?2800new (persistentMemory()) TR::CompilationInfoPerThreadRemote(*this, _jitConfig, threadId, isDiagnosticThread) :2801new (persistentMemory()) TR::CompilationInfoPerThread(*this, _jitConfig, threadId, isDiagnosticThread);2802#else2803TR::CompilationInfoPerThread *compInfoPT = new (persistentMemory()) TR::CompilationInfoPerThread(*this, _jitConfig, threadId, isDiagnosticThread);2804#endif /* defined(J9VM_OPT_JITSERVER) */28052806if (!compInfoPT || !compInfoPT->initializationSucceeded() || !compInfoPT->getCompThreadMonitor())2807return 1; // TODO must deallocate some things in compInfoPT as well as the memory for it28082809int32_t jitPriority;2810if (priority < 0)2811{2812jitPriority = computeCompilationThreadPriority(vm);2813if (TR::Options::getCmdLineOptions()->realTimeGC())2814{2815static char *incMaxPriority = feGetEnv("IBM_J9_THREAD_INCREMENT_MAX_PRIORITY");2816static char *decJitPriority = feGetEnv("TR_DECREMENT_JIT_COMPILATION_PRIORITY");2817if (incMaxPriority && decJitPriority)2818jitPriority--;2819}2820}28212822compInfoPT->setCompThreadPriority(priority < 0 ? jitPriority : priority);28232824// add this entry to the array in the compilationInfo object2825// NOTE: This method must be issued by a single thread because we don't hold a monitor.2826_arrayOfCompilationInfoPerThread[compInfoPT->getCompThreadId()] = compInfoPT;28272828// NOTE:2829// variable (_numDiagnosticThreads) updates are wrapped in monitor to prevent instruction re-ordering2830// since the order of updates matters and MUST be done AFTER _arrayOfCompilationInfoPerThread2831// is updated; for example on PPC, these two statements may be done in the wrong order;2832// the calls to the monitor insert synchronization instructions and prevent this2833if (isDiagnosticThread)2834{2835getCompilationMonitor()->enter();2836_compInfoForDiagnosticCompilationThread = compInfoPT;2837_numDiagnosticThreads++;2838getCompilationMonitor()->exit();2839}2840else2841{2842getCompilationMonitor()->enter();2843_numCompThreads++;2844getCompilationMonitor()->exit();2845}28462847//_methodQueue = NULL; This is initialized when compInfo is created2848debugPrint("\t\tstarting compilation thread\n");28492850if (vm->internalVMFunctions->createThreadWithCategory(&compInfoPT->_osThread,2851TR::Options::_stackSize << 10, // stack size in kb2852compInfoPT->getCompThreadPriority(),28530, // allow thread to start immediately2854(j9thread_entrypoint_t)compilationThreadProc,2855compInfoPT,2856J9THREAD_CATEGORY_SYSTEM_JIT_THREAD))2857{2858//_compilationMonitor->destroy();2859//_compilationMonitor = NULL;2860// TODO must do some cleanup2861return 2;2862}28632864// Would like to wait here until the compThread attaches to the VM2865compInfoPT->getCompThreadMonitor()->enter();2866while ( !compInfoPT->getCompilationThread() && compInfoPT->getCompilationThreadState() != COMPTHREAD_ABORT )2867compInfoPT->getCompThreadMonitor()->wait(); // for the compThread to be initialized2868compInfoPT->getCompThreadMonitor()->exit();28692870if (compInfoPT->getCompilationThreadState() == COMPTHREAD_ABORT)2871return 3;28722873return 0;2874}28752876#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)2877void *TR::CompilationInfo::searchForDLTRecord(J9Method *method, int32_t bcIndex)2878{2879int32_t hashVal = (intptr_t)method * bcIndex % DLT_HASHSIZE;2880if (hashVal < 0)2881hashVal = -hashVal;28822883//_dltMonitor->enter();2884struct DLT_record *dltPtr;28852886// When bcIndex is negative(invalid) I have to scan the entire hashtable2887// for a matching j9method2888if (bcIndex < 0)2889{2890for (int32_t i=0; i<DLT_HASHSIZE; i++)2891{2892dltPtr = _dltHash[i];2893while (dltPtr != NULL)2894{2895if (dltPtr->_method==method)2896{2897//_dltMonitor->exit();2898return dltPtr->_dltEntry;2899}2900dltPtr = dltPtr->_next;2901}2902}2903}2904else2905{2906dltPtr = _dltHash[hashVal];2907while (dltPtr != NULL)2908{2909if (dltPtr->_method==method && dltPtr->_bcIndex==bcIndex)2910{2911// Safe: since we are not giving up on vmAccess yet2912//_dltMonitor->exit();2913return dltPtr->_dltEntry;2914}2915dltPtr = dltPtr->_next;2916}2917}2918//_dltMonitor->exit();2919return NULL;2920}29212922void TR::CompilationInfo::insertDLTRecord(J9Method *method, int32_t bcIndex, void *dltEntry)2923{2924int32_t hashVal = (intptr_t)method * bcIndex % DLT_HASHSIZE;2925if (hashVal < 0)2926hashVal = -hashVal;29272928{2929OMR::CriticalSection updatingDLTRecords(_dltMonitor);2930struct DLT_record *dltPtr = _dltHash[hashVal];29312932while (dltPtr != NULL)2933{2934if (dltPtr->_method == method && dltPtr->_bcIndex == bcIndex)2935{2936return;2937}2938dltPtr = dltPtr->_next;2939}29402941struct DLT_record *myRecord;29422943if (_freeDLTRecord != NULL)2944{2945myRecord = _freeDLTRecord;2946_freeDLTRecord = myRecord->_next;2947}2948else2949myRecord = (struct DLT_record *)jitPersistentAlloc(sizeof(struct DLT_record));29502951if (!myRecord)2952{2953return;2954}29552956myRecord->_method = method;2957myRecord->_bcIndex = bcIndex;2958myRecord->_dltEntry = dltEntry;2959myRecord->_next = _dltHash[hashVal];2960// Memory Flush (for PPC) so myRecord is visible to other CPUs before we update the _dltHash2961// Doing this means we don't need locking when reading the _dltHash linked lists2962FLUSH_MEMORY(TR::Compiler->target.isSMP());2963_dltHash[hashVal] = myRecord;2964}2965}29662967void TR::CompilationInfo::cleanDLTRecordOnUnload()2968{2969for (int32_t i=0; i<DLT_HASHSIZE; i++)2970{2971struct DLT_record *prev=NULL, *curr=_dltHash[i], *next;2972while (curr != NULL)2973{2974J9Class *clazz = J9_CLASS_FROM_METHOD(curr->_method);2975next = curr->_next;29762977// Non-Anon classes will be unloaded with their classloaders, hence the class's classloader will be marked as dead.2978// Anon Classes can be independently unloaded without their classloaders, however their classes are marked as dying.2979if ( J9_ARE_ALL_BITS_SET(clazz->classLoader->gcFlags, J9_GC_CLASS_LOADER_DEAD)2980|| (J9CLASS_FLAGS(clazz) & J9AccClassDying) )2981{2982if (prev == NULL)2983_dltHash[i] = next;2984else2985prev->_next = next;29862987// FIXME: free the codeCache2988curr->_next = _freeDLTRecord;2989_freeDLTRecord = curr;2990}2991else2992prev = curr;2993curr = next;2994}2995}2996}2997#endif29982999#ifdef INVOCATION_STATS3000extern "C" J9Method * getNewInstancePrototype(J9VMThread * context);3001#include "infra/Statistics.hpp"3002void printAllCounts(J9JavaVM *javaVM)3003{3004J9VMThread *vmThread = javaVM->internalVMFunctions->currentVMThread(javaVM);3005J9ClassWalkState classWalkState;3006TR_StatsHisto<30> statsInvocationCountLoopy("Stats inv. count loopy methods", 5, 155);3007TR_StatsHisto<30> statsInvocationCountLoopless("Stats inv. count loopless methods", 5, 155);3008int32_t numMethodsNeverInvoked = 0;3009J9Class * clazz = javaVM->internalVMFunctions->allClassesStartDo(&classWalkState, javaVM, NULL);30103011while (clazz)3012{30133014if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(clazz->romClass))3015{3016J9Method * newInstanceThunk = getNewInstancePrototype(vmThread);3017J9Method * ramMethods = (J9Method *) (clazz->ramMethods);3018for (int32_t m = 0; m < clazz->romClass->romMethodCount; m++)3019{3020J9Method * method = &ramMethods[m];3021J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);3022if (!(romMethod->modifiers & (J9AccNative | J9AccAbstract)) &&3023method != newInstanceThunk &&3024!TR::CompilationInfo::isCompiled(method))3025{3026// Print the count for the interpreted method3027/*3028J9UTF8 *utf8;3029utf8 = J9ROMCLASS_CLASSNAME(clazz->romClass);3030fprintf(stderr, "%.*s", J9UTF8_LENGTH(utf8), (char *) J9UTF8_DATA(utf8));3031utf8 = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(method));3032fprintf(stderr, ".%.*s", J9UTF8_LENGTH(utf8), (char *) J9UTF8_DATA(utf8));3033utf8 = J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(method));3034fprintf(stderr, "%.*s", J9UTF8_LENGTH(utf8), (char *) J9UTF8_DATA(utf8));3035*/3036intptr_t count = (intptr_t) TR::CompilationInfo::getInvocationCount(method);3037if (count < 0)3038{3039fprintf(stderr, "Bad count\n");3040}3041else3042{3043//fprintf(stderr, " extra=%d ", count);3044intptr_t initialCount = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR::Options::getCmdLineOptions()->getInitialBCount() : TR::Options::getCmdLineOptions()->getInitialCount();3045if (count > initialCount)3046{3047fprintf(stderr, " Bad count\n");3048}3049else3050{3051intptr_t invocationCount = initialCount - count;3052//fprintf(stderr, " invocation count=%d\n", invocationCount);3053if (invocationCount==0 || count == 0) // some methods have count==0 and are never invoked3054{3055numMethodsNeverInvoked++;3056}3057else3058{3059if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))3060statsInvocationCountLoopy.update((double)invocationCount);3061else3062statsInvocationCountLoopless.update((double)invocationCount);3063}3064}3065}3066}3067}3068}3069clazz = javaVM->internalVMFunctions->allClassesNextDo(&classWalkState);3070}3071javaVM->internalVMFunctions->allClassesEndDo(&classWalkState);3072statsInvocationCountLoopy.report(stderr);3073statsInvocationCountLoopless.report(stderr);3074fprintf(stderr, "Methods never invoked = %d\n", numMethodsNeverInvoked);3075}3076#endif // INVOCATION_STATS30773078#include "infra/Statistics.hpp" // MCT30793080void TR::CompilationInfo::stopCompilationThreads()3081{3082J9JavaVM * const vm = _jitConfig->javaVM;3083J9VMThread * const vmThread = vm->internalVMFunctions->currentVMThread(vm);30843085static char * printCompStats = feGetEnv("TR_PrintCompStats");3086if (printCompStats)3087{3088if (statCompErrors.samples() > 0)3089statCompErrors.report(stderr);30903091fprintf(stderr, "Number of compilations per level:\n");3092for (int i = 0; i < (int)numHotnessLevels; i++)3093{3094if (_statsOptLevels[i] > 0)3095{3096fprintf(stderr, "Level=%d\tnumComp=%d", i, _statsOptLevels[i]);3097#if defined(J9VM_OPT_JITSERVER)3098if (_statsRemoteOptLevels[i] > 0)3099fprintf(stderr, "\tnumRemoteComp=%d", _statsRemoteOptLevels[i]);3100#endif /* defined(J9VM_OPT_JITSERVER) */3101fprintf(stderr, "\n");3102}3103}31043105if (_statNumJNIMethodsCompiled > 0)3106fprintf(stderr, "NumJNIMethodsCompiled=%u\n", _statNumJNIMethodsCompiled);3107if (numMethodsFoundInSharedCache() > 0)3108fprintf(stderr, "NumMethodsFoundInSharedCache=%d\n", numMethodsFoundInSharedCache());3109if (_statNumMethodsFromSharedCache)3110fprintf(stderr, "NumMethodsTakenFromSharedCache=%u\n", _statNumMethodsFromSharedCache);3111if (_statNumAotedMethods)3112fprintf(stderr, "NumAotedMethods=%u\n", _statNumAotedMethods);3113if (_statNumAotedMethodsRecompiled)3114fprintf(stderr, "NumberOfAotedMethodsThatWereRecompiled=%u (forced=%d)\n", _statNumAotedMethodsRecompiled, _statNumForcedAotUpgrades);3115if (_statTotalAotQueryTime)3116fprintf(stderr, "Time spent querying shared cache for methods: %u ms\n", _statTotalAotQueryTime/1000);31173118if (getHWProfiler() && TR_HWProfiler::_STATS_NumUpgradesDueToRI > 0)3119fprintf(stderr, "numUpgradesDueToRI=%u\n", TR_HWProfiler::_STATS_NumUpgradesDueToRI);31203121fprintf(stderr, "Classes loaded=%d\n", getPersistentInfo()->getNumLoadedClasses());31223123// assumptionTableMutex is not used, so the numbers may be a little off3124fprintf(stderr, "\tStats on assumptions:\n");3125TR_RuntimeAssumptionTable * rat = getPersistentInfo()->getRuntimeAssumptionTable();3126int32_t unreclaimedAssumptions = 0;3127for (int32_t i=0; i < LastAssumptionKind; i++)3128{3129fprintf(stderr, "\tAssumptionType=%d allocated=%d reclaimed=%d\n", i, rat->getAssumptionCount(i), rat->getReclaimedAssumptionCount(i));3130unreclaimedAssumptions += rat->getAssumptionCount(i) - rat->getReclaimedAssumptionCount(i);3131}3132int32_t assumptionsInRAT = rat->countRatAssumptions();3133fprintf(stderr, "Summary of assumptions: unreclaimed=%d, in RAT=%d\n", unreclaimedAssumptions, rat->countRatAssumptions());31343135fprintf(stderr, "GCR bodies=%d, GCRSaves=%d GCRRecomp=%u\n",3136getPersistentInfo()->getNumGCRBodies(),3137getPersistentInfo()->getNumGCRSaves(),3138_statNumGCRInducedCompilations);3139if (_statNumSamplingJProfilingBodies != 0)3140fprintf(stderr, "SamplingJProfiling bodies=%u\n", _statNumSamplingJProfilingBodies);3141if (_statNumJProfilingBodies != 0)3142fprintf(stderr, "Jprofiling bodies=%u\n", _statNumJProfilingBodies);3143if (_statNumMethodsFromJProfilingQueue != 0)3144fprintf(stderr, "Recompilation for bodies with JProfiling=%u\n", _statNumMethodsFromJProfilingQueue);3145if (_statNumRecompilationForBodiesWithJProfiling != 0)3146fprintf(stderr, "Methods taken from the queue with JProfiling requests=%u\n", _statNumRecompilationForBodiesWithJProfiling);31473148#ifdef INVOCATION_STATS3149printAllCounts(_jitConfig->javaVM);3150#endif31513152getLowPriorityCompQueue().printStats();31533154fprintf(stderr, "Compilation queue peak size = %d\n", getPeakMethodQueueSize());3155fprintf(stderr, "Compilation queue size at shutdown = %d\n", getMethodQueueSize());3156#ifdef MCT_STATS3157statCompReqResidencyTime.report(stderr); // MCT3158statCompReqProcessingTime.report(stderr); // MCT3159statNumReqForProcessing.report(stderr); // MCT3160fprintf(stderr, "NumberOfActivations=%u number of suspensions=%u\n", numCompThreadsActivations, numCompThreadsSuspensions);3161#endif3162} // if (printCompStats)31633164if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableAOTRelocationTiming))3165{3166fprintf(stderr, "Time spent relocating all AOT methods: %u ms\n", this->getAotRelocationTime()/1000);3167}31683169static char * printCompMem = feGetEnv("TR_PrintCompMem");3170static char * printCCUsage = feGetEnv("TR_PrintCodeCacheUsage");31713172// Example:3173// CodeCache: size=262144Kb used=2048Kb max_used=1079Kb free=260096Kb3174if (TR::Options::getCmdLineOptions()->getOption(TR_PrintCodeCacheUsage) || printCompMem || printCCUsage)3175{3176unsigned long currTotalUsedKB = (unsigned long)(TR::CodeCacheManager::instance()->getCurrTotalUsedInBytes()/1024);3177unsigned long maxUsedKB = (unsigned long)(TR::CodeCacheManager::instance()->getMaxUsedInBytes()/1024);31783179fprintf(stderr, "\nCodeCache: size=%" OMR_PRIuPTR "Kb used=%luKb max_used=%luKb free=%" OMR_PRIuPTR "Kb\n\n",3180_jitConfig->codeCacheTotalKB,3181currTotalUsedKB,3182maxUsedKB,3183(_jitConfig->codeCacheTotalKB - currTotalUsedKB));3184}31853186if (printCompMem)3187{3188int32_t codeCacheAllocated = TR::CodeCacheManager::instance()->getCurrentNumberOfCodeCaches() * _jitConfig->codeCacheKB;3189fprintf(stderr, "Allocated memory for code cache = %d KB\tLimit = %" OMR_PRIuPTR " KB\n",3190codeCacheAllocated, _jitConfig->codeCacheTotalKB);31913192TR::CodeCacheManager::instance()->printMccStats();31933194fprintf(stderr, "Allocated memory for data cache = %d KB\tLimit = %" OMR_PRIuPTR " KB\n",3195TR_DataCacheManager::getManager()->getTotalSegmentMemoryAllocated()/1024,3196_jitConfig->dataCacheTotalKB);31973198if (getJProfilerThread())3199fprintf(stderr, "Allocated memory for profile info = %" OMR_PRIdSIZE " KB\n", getJProfilerThread()->getProfileInfoFootprint()/1024);3200}32013202static char * printPersistentMem = feGetEnv("TR_PrintPersistentMem");3203if (printPersistentMem)3204{3205if (trPersistentMemory)3206trPersistentMemory->printMemStats();3207}32083209TR_DataCacheManager::getManager()->printStatistics();32103211bool aotStatsEnabled = TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableAOTStats);3212if (aotStatsEnabled)3213{3214fprintf(stderr, "AOT code compatible: %d\n", static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader);32153216TR_AOTStats *aotStats = ((TR_JitPrivateConfig *)_jitConfig->privateConfig)->aotStats;3217fprintf(stderr, "AOT failedPerfAssumptionCode: %d\n", aotStats->failedPerfAssumptionCode);3218fprintf(stderr, "COMPILE TIME INFO ------\n");3219fprintf(stderr, "numCHEntriesAlreadyStoredInLocalList: %d\n", aotStats->numCHEntriesAlreadyStoredInLocalList);3220fprintf(stderr, "numNewCHEntriesInLocalList: %d\n", aotStats->numNewCHEntriesInLocalList);3221fprintf(stderr, "numNewCHEntriesInSharedClass: %d\n", aotStats->numNewCHEntriesInSharedClass);3222fprintf(stderr, "numEntriesFoundInLocalChain: %d\n", aotStats->numEntriesFoundInLocalChain);3223fprintf(stderr, "numEntriesFoundAndValidatedInSharedClass: %d\n", aotStats->numEntriesFoundAndValidatedInSharedClass);3224fprintf(stderr, "numClassChainNotInSharedClass: %d\n", aotStats->numClassChainNotInSharedClass);3225fprintf(stderr, "numCHInSharedCacheButFailValiation: %d\n", aotStats->numCHInSharedCacheButFailValiation);3226fprintf(stderr, "numInstanceFieldInfoNotUsed: %d\n", aotStats->numInstanceFieldInfoNotUsed);3227fprintf(stderr, "numStaticFieldInfoNotUsed: %d\n", aotStats->numStaticFieldInfoNotUsed);3228fprintf(stderr, "numDefiningClassNotFound: %d\n", aotStats->numDefiningClassNotFound);3229fprintf(stderr, "numInstanceFieldInfoUsed: %d\n", aotStats->numInstanceFieldInfoUsed);3230fprintf(stderr, "numStaticFieldInfoUsed: %d\n", aotStats->numStaticFieldInfoUsed);3231fprintf(stderr, "numCannotGenerateHashForStore: %d\n", aotStats->numCannotGenerateHashForStore);32323233fprintf(stderr, "-------------------------\n");3234fprintf(stderr, "RUNTIME INFO -----------\n");32353236fprintf(stderr, "numRuntimeChainNotFound: %d\n", aotStats->numRuntimeChainNotFound);3237fprintf(stderr, "numRuntimeStaticFieldUnresolvedCP: %d\n", aotStats->numRuntimeStaticFieldUnresolvedCP);3238fprintf(stderr, "numRuntimeInstanceFieldUnresolvedCP: %d\n", aotStats->numRuntimeInstanceFieldUnresolvedCP);3239fprintf(stderr, "numRuntimeUnresolvedStaticFieldFromCP: %d\n", aotStats->numRuntimeUnresolvedStaticFieldFromCP);3240fprintf(stderr, "numRuntimeUnresolvedInstanceFieldFromCP: %d\n", aotStats->numRuntimeUnresolvedInstanceFieldFromCP);3241fprintf(stderr, "numRuntimeResolvedStaticFieldButFailValidation: %d\n", aotStats->numRuntimeResolvedStaticFieldButFailValidation);3242fprintf(stderr, "numRuntimeResolvedInstanceFieldButFailValidation: %d\n", aotStats->numRuntimeResolvedInstanceFieldButFailValidation);3243fprintf(stderr, "numRuntimeStaticFieldReloOK: %d\n", aotStats->numRuntimeStaticFieldReloOK);3244fprintf(stderr, "numRuntimeInstanceFieldReloOK: %d\n", aotStats->numRuntimeInstanceFieldReloOK);32453246fprintf(stderr, "numRuntimeClassAddressUnresolvedCP: %d\n", aotStats->numRuntimeClassAddressUnresolvedCP);3247fprintf(stderr, "numRuntimeClassAddressFromCP: %d\n", aotStats->numRuntimeClassAddressFromCP);3248fprintf(stderr, "numRuntimeClassAddressButFailValidation: %d\n", aotStats->numRuntimeClassAddressButFailValidation);3249fprintf(stderr, "numRuntimeClassAddressReloOK: %d\n", aotStats->numRuntimeClassAddressReloOK);32503251fprintf(stderr, "numRuntimeClassAddressRelocationCount: %d\n", aotStats->numRuntimeClassAddressRelocationCount);3252fprintf(stderr, "numRuntimeClassAddressReloUnresolvedCP: %d\n", aotStats->numRuntimeClassAddressReloUnresolvedCP);3253fprintf(stderr, "numRuntimeClassAddressReloUnresolvedClass: %d\n", aotStats->numRuntimeClassAddressReloUnresolvedClass);32543255fprintf(stderr, "numClassValidations: %d\n", aotStats->numClassValidations);3256fprintf(stderr, "numClassValidationsFailed: %d\n", aotStats->numClassValidationsFailed);3257fprintf(stderr, "numWellKnownClassesValidationsFailed: %d\n", aotStats->numWellKnownClassesValidationsFailed);32583259fprintf(stderr, "numVMCheckCastEvaluator (x86): %d\n", aotStats->numVMCheckCastEvaluator);3260fprintf(stderr, "numVMInstanceOfEvaluator (x86): %d\n", aotStats->numVMInstanceOfEvaluator);3261fprintf(stderr, "numVMIfInstanceOfEvaluator (x86): %d\n", aotStats->numVMIfInstanceOfEvaluator);3262fprintf(stderr, "numCheckCastVMHelperInstructions (x86): %d\n", aotStats->numCheckCastVMHelperInstructions);3263fprintf(stderr, "numInstanceOfVMHelperInstructions (x86): %d\n", aotStats->numInstanceOfVMHelperInstructions);3264fprintf(stderr, "numIfInstanceOfVMHelperInstructions (x86): %d\n", aotStats->numIfInstanceOfVMHelperInstructions);326532663267fprintf(stderr, "-------------------------\n");3268fprintf(stderr, "AOT METHOD INLINING COMPILE TIME INFO ------\n");32693270fprintf(stderr, "numStaticMethodFromDiffClassLoader: %d\n", aotStats->staticMethods.numMethodFromDiffClassLoader);3271fprintf(stderr, "numStaticMethodInSameClass: %d\n", aotStats->staticMethods.numMethodInSameClass);3272fprintf(stderr, "numStaticMethodNotInSameClass: %d\n", aotStats->staticMethods.numMethodNotInSameClass);3273fprintf(stderr, "numStaticMethodResolvedAtCompile: %d\n", aotStats->staticMethods.numMethodResolvedAtCompile);3274fprintf(stderr, "numStaticMethodNotResolvedAtCompile: %d\n", aotStats->staticMethods.numMethodNotResolvedAtCompile);3275fprintf(stderr, "numStaticMethodROMMethodNotInSC: %d\n", aotStats->staticMethods.numMethodROMMethodNotInSC);32763277fprintf(stderr, "numSpecialMethodFromDiffClassLoader: %d\n", aotStats->specialMethods.numMethodFromDiffClassLoader);3278fprintf(stderr, "numSpecialMethodInSameClass: %d\n", aotStats->specialMethods.numMethodInSameClass);3279fprintf(stderr, "numSpecialMethodNotInSameClass: %d\n", aotStats->specialMethods.numMethodNotInSameClass);3280fprintf(stderr, "numSpecialMethodResolvedAtCompile: %d\n", aotStats->specialMethods.numMethodResolvedAtCompile);3281fprintf(stderr, "numSpecialMethodNotResolvedAtCompile: %d\n", aotStats->specialMethods.numMethodNotResolvedAtCompile);3282fprintf(stderr, "numSpecialMethodROMMethodNotInSC: %d\n", aotStats->specialMethods.numMethodROMMethodNotInSC);32833284fprintf(stderr, "numVirtualMethodFromDiffClassLoader: %d\n", aotStats->virtualMethods.numMethodFromDiffClassLoader);3285fprintf(stderr, "numVirtualMethodInSameClass: %d\n", aotStats->virtualMethods.numMethodInSameClass);3286fprintf(stderr, "numVirtualMethodNotInSameClass: %d\n", aotStats->virtualMethods.numMethodNotInSameClass);3287fprintf(stderr, "numVirtualMethodResolvedAtCompile: %d\n", aotStats->virtualMethods.numMethodResolvedAtCompile);3288fprintf(stderr, "numVirtualMethodNotResolvedAtCompile: %d\n", aotStats->virtualMethods.numMethodNotResolvedAtCompile);3289fprintf(stderr, "numVirtualMethodROMMethodNotInSC: %d\n", aotStats->virtualMethods.numMethodROMMethodNotInSC);32903291fprintf(stderr, "numInterfaceMethodFromDiffClassLoader: %d\n", aotStats->interfaceMethods.numMethodFromDiffClassLoader);3292fprintf(stderr, "numInterfaceMethodInSameClass: %d\n", aotStats->interfaceMethods.numMethodInSameClass);3293fprintf(stderr, "numInterfaceMethodNotInSameClass: %d\n", aotStats->interfaceMethods.numMethodNotInSameClass);3294fprintf(stderr, "numInterfaceMethodResolvedAtCompile: %d\n", aotStats->interfaceMethods.numMethodResolvedAtCompile);3295fprintf(stderr, "numInterfaceMethodNotResolvedAtCompile: %d\n", aotStats->interfaceMethods.numMethodNotResolvedAtCompile);3296fprintf(stderr, "numInterfaceMethodROMMethodNotInSC: %d\n", aotStats->interfaceMethods.numMethodROMMethodNotInSC);32973298fprintf(stderr, "-------------------------\n");32993300fprintf(stderr, "AOT METHOD INLINING RUNTIME INFO ------\n");33013302fprintf(stderr, "numInlinedMethodOverridden: %d\n", aotStats->numInlinedMethodOverridden);3303fprintf(stderr, "numInlinedMethodNotResolved: %d\n", aotStats->numInlinedMethodNotResolved);3304fprintf(stderr, "numInlinedMethodClassNotMatch: %d\n", aotStats->numInlinedMethodClassNotMatch);3305fprintf(stderr, "numInlinedMethodCPNotResolved: %d\n", aotStats->numInlinedMethodCPNotResolved);3306fprintf(stderr, "numInlinedMethodRelocated: %d\n", aotStats->numInlinedMethodRelocated);3307fprintf(stderr, "numInlinedMethodValidationFailed: %d\n", aotStats->numInlinedMethodValidationFailed);33083309fprintf(stderr, "numDataAddressRelosSucceed: %d\n", aotStats->numDataAddressRelosSucceed);3310fprintf(stderr, "numDataAddressRelosFailed: %d\n", aotStats->numDataAddressRelosFailed);33113312fprintf(stderr, "-------------------------\n");33133314fprintf(stderr, "numStaticMethodsValidationFailed: %d\n", aotStats->staticMethods.numFailedValidations);3315fprintf(stderr, "numStaticMethodsValidationSucceeded: %d\n", aotStats->staticMethods.numSucceededValidations);3316fprintf(stderr, "numSpecialMethodsValidationFailed: %d\n", aotStats->specialMethods.numFailedValidations);3317fprintf(stderr, "numSpecialMethodsValidationSucceeded: %d\n", aotStats->specialMethods.numSucceededValidations);3318fprintf(stderr, "numVirtualMethodsValidationFailed: %d\n", aotStats->virtualMethods.numFailedValidations);3319fprintf(stderr, "numVirtualMethodsValidationSucceeded: %d\n", aotStats->virtualMethods.numSucceededValidations);3320fprintf(stderr, "numInterfaceMethodsValidationFailed: %d\n", aotStats->interfaceMethods.numFailedValidations);3321fprintf(stderr, "numInterfaceMethodsValidationSucceeded: %d\n", aotStats->interfaceMethods.numSucceededValidations);3322fprintf(stderr, "numAbstractMethodsValidationFailed: %d\n", aotStats->abstractMethods.numFailedValidations);3323fprintf(stderr, "numAbstractMethodsValidationSucceeded: %d\n", aotStats->abstractMethods.numSucceededValidations);33243325fprintf(stderr, "-------------------------\n");3326fprintf(stderr, "numProfiledClassGuardsValidationFailed: %d\n", aotStats->profiledClassGuards.numFailedValidations);3327fprintf(stderr, "numProfiledClassGuardsValidationSucceeded: %d\n", aotStats->profiledClassGuards.numSucceededValidations);3328fprintf(stderr, "numProfiledMethodGuardsValidationFailed: %d\n", aotStats->profiledMethodGuards.numFailedValidations);3329fprintf(stderr, "numProfiledMethodGuardsValidationSucceeded: %d\n", aotStats->profiledMethodGuards.numSucceededValidations);3330fprintf(stderr, "-------------------------\n");33313332fprintf(stderr, "RELO FAILURES BY TYPE ------\n");3333for (uint32_t i = 0; i < TR_NumExternalRelocationKinds; i++)3334{3335fprintf(stderr, "%s: %d\n", TR::ExternalRelocation::getName((TR_ExternalRelocationTargetKind)i), aotStats->numRelocationsFailedByType[i]);3336}3337fprintf(stderr, "-------------------------\n");33383339} // AOT stats334033413342if (printCompStats && (dynamicThreadPriority() || compBudgetSupport()))3343{3344fprintf(stderr, "Number of yields =%4u\n", _statNumYields);3345fprintf(stderr, "NumPriorityChanges=%4u\n", _statNumPriorityChanges);3346fprintf(stderr, "NumUpgradeInterpretedMethod =%u\n", _statNumUpgradeInterpretedMethod);3347fprintf(stderr, "NumDowngradeInterpretedMethod=%u\n", _statNumDowngradeInterpretedMethod);3348fprintf(stderr, "NumUpgradeJittedMethod=%u\n", _statNumUpgradeJittedMethod);3349fprintf(stderr, "NumQueuePromotions=%u\n", _statNumQueuePromotions);3350}33513352#if defined(J9VM_OPT_JITSERVER)3353static char *printJITServerIPMsgStats = feGetEnv("TR_PrintJITServerIPMsgStats");3354if (printJITServerIPMsgStats)3355{3356if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)3357{3358TR_J9VMBase *vmj9 = (TR_J9VMBase *)TR_J9VMBase::get(_jitConfig, NULL);3359JITServerIProfiler *iProfiler = (JITServerIProfiler *)vmj9->getIProfiler();3360iProfiler->printStats();3361}3362}33633364static char *printJITServerConnStats = feGetEnv("TR_PrintJITServerConnStats");3365if (printJITServerConnStats)3366{3367if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)3368{3369fprintf(stderr, "Number of connections opened = %u\n", JITServer::ServerStream::getNumConnectionsOpened());3370fprintf(stderr, "Number of connections closed = %u\n", JITServer::ServerStream::getNumConnectionsClosed());3371}3372else if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)3373{3374fprintf(stderr, "Number of connections opened = %u\n", JITServer::ClientStream::getNumConnectionsOpened());3375fprintf(stderr, "Number of connections closed = %u\n", JITServer::ClientStream::getNumConnectionsClosed());3376}3377}33783379static char *printJITServerAOTCacheStats = feGetEnv("TR_PrintJITServerAOTCacheStats");3380if (printJITServerAOTCacheStats)3381{3382if (auto aotCacheMap = getJITServerAOTCacheMap())3383aotCacheMap->printStats(stderr);3384if (auto deserializer = getJITServerAOTDeserializer())3385deserializer->printStats(stderr);3386}3387#endif /* defined(J9VM_OPT_JITSERVER) */33883389#ifdef STATS3390if (compBudgetSupport() || dynamicThreadPriority())3391{3392fprintf(stderr, "Compilation request queue size at shutdown=%d\n", getMethodQueueSize());3393statQueueSize.report(stderr);3394if (compBudgetSupport())3395{3396statBudgetEpoch.report(stderr);3397statBudgetSmallLag.report(stderr);3398statBudgetMediumLag.report(stderr);3399statEpochLength.report(stderr);3400}3401statEvents.report(stderr);3402statLowPriority.report(stderr);3403statLowBudget.report(stderr);3404statOverhead.report(stderr);3405}3406#endif3407acquireCompMonitor(vmThread);34083409// Cycle through all non-diagnostic threads and stop them3410for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)3411{3412TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];34133414if (!curCompThreadInfoPT->isDiagnosticThread())3415stopCompilationThread(curCompThreadInfoPT);3416}34173418TR_ASSERT_FATAL(getNumCompThreadsActive() == 0, "All threads must be inactive at this point\n");34193420purgeMethodQueue(compilationSuspended);34213422// Cycle though all non-diagnostic threads and wait for them to terminate. At this point it is possible that a3423// compilation thread has crashed and is going through the JitDump process. The reason we skipped terminating the3424// diagnostic threads in the above loop is because the JitDump logic will activate the diagnostic thread to generate3425// the JitDump, so the diagnostic thread must not be in a terminated state at that point.3426for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)3427{3428TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];34293430if (!curCompThreadInfoPT->isDiagnosticThread())3431{3432while (curCompThreadInfoPT->getCompilationThreadState() != COMPTHREAD_STOPPED)3433{3434getCompilationMonitor()->notifyAll();3435waitOnCompMonitor(vmThread);3436}3437}3438}34393440// Now that all compilation threads have terminated, we are sure none of them have crashed, or they have finished3441// generating a JitDump. Only at this point can we terminate the diagnostic threads. If a compilation thread did3442// crash we will actually never execute code following this comment. This is because the crashed thread will be3443// in an active state, since it has crashed during a compilation, and the we will be waiting on the comp monitor3444// for the crashed thread in the loop above. However because the diagnostic data is generated on the crashed3445// thread this thread will never return to execute the state processing loop, and thus will never terminate.3446// This is ok, because following the dump process in the JVM we will terminate the entire JVM process.3447for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)3448{3449TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];34503451if (curCompThreadInfoPT->isDiagnosticThread())3452stopCompilationThread(curCompThreadInfoPT);3453}34543455// Wake up the diagnostic thread and stop it. If it is currently active then we will block here until the JitDump3456// process is complete (see #11860).3457for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)3458{3459TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];34603461if (curCompThreadInfoPT->isDiagnosticThread())3462{3463while (curCompThreadInfoPT->getCompilationThreadState() != COMPTHREAD_STOPPED)3464{3465getCompilationMonitor()->notifyAll();3466waitOnCompMonitor(vmThread);3467}3468}3469}34703471// Remove the method pool entries3472//3473PORT_ACCESS_FROM_JAVAVM(_jitConfig->javaVM);3474while (_methodPool)3475{3476TR_MethodToBeCompiled *next = _methodPool->_next;3477if (_methodPool->_numThreadsWaiting == 0)3478{3479_methodPool->shutdown();3480j9mem_free_memory(_methodPool);3481}3482else // Some thread may need this entry after the waiting thread resumes activity3483{3484_methodPool->_entryShouldBeDeallocated = true;3485}3486_methodPool = next;3487}3488#ifdef LINUX3489// Now that all compilation threads are stopped we can close the perfFile stream3490if (TR::CompilationInfoPerThreadBase::getPerfFile())3491{3492// Generate any non-method entries (trampolines, etc) that are present in each codecache3493TR::CodeCacheManager *manager = TR::CodeCacheManager::instance();3494for (TR::CodeCache *cc = manager->getFirstCodeCache(); cc; cc = cc->getNextCodeCache())3495{3496cc->generatePerfToolEntries(TR::CompilationInfoPerThreadBase::getPerfFile());3497}34983499j9jit_fclose(TR::CompilationInfoPerThreadBase::getPerfFile());3500TR::CompilationInfoPerThreadBase::setPerfFile(NULL); // prevent closing twice3501}3502#endif35033504releaseCompMonitor(vmThread);3505#if defined(J9VM_OPT_JITSERVER)3506if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)3507{3508try3509{3510JITServer::ClientStream client(getPersistentInfo());3511client.writeError(JITServer::MessageType::clientSessionTerminate, getPersistentInfo()->getClientUID());3512}3513catch (const JITServer::StreamFailure &e)3514{3515JITServerHelpers::postStreamFailure(OMRPORT_FROM_J9PORT(_jitConfig->javaVM->portLibrary), this);3516// catch the stream failure exception if the server dies before the dummy message is send for termination.3517if (TR::Options::getVerboseOption(TR_VerboseJITServer))3518TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "JITServer StreamFailure (server unreachable before the termination message was sent): %s", e.what());3519}3520}3521#endif /* defined(J9VM_OPT_JITSERVER) */3522}35233524void TR::CompilationInfo::stopCompilationThread(CompilationInfoPerThread* compInfoPT)3525{3526compInfoPT->setCompilationShouldBeInterrupted(SHUTDOWN_COMP_INTERRUPT);35273528switch (compInfoPT->getCompilationThreadState())3529{3530case COMPTHREAD_SUSPENDED:3531compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);3532compInfoPT->getCompThreadMonitor()->enter();3533compInfoPT->getCompThreadMonitor()->notifyAll();3534compInfoPT->getCompThreadMonitor()->exit();3535break;35363537case COMPTHREAD_ACTIVE:3538case COMPTHREAD_SIGNAL_WAIT:3539case COMPTHREAD_WAITING:3540compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);35413542if (!compInfoPT->isDiagnosticThread())3543decNumCompThreadsActive();3544break;35453546case COMPTHREAD_SIGNAL_SUSPEND:3547compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);3548break;35493550case COMPTHREAD_SIGNAL_TERMINATE:3551case COMPTHREAD_STOPPING:3552case COMPTHREAD_STOPPED:3553// Weird case; we should not do anything3554break;35553556case COMPTHREAD_UNINITIALIZED:3557// Compilation thread did not have time to become fully initialized3558compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);3559break;35603561default:3562TR_ASSERT_FATAL(false, "No other comp thread state possible here");3563}3564}35653566IDATA J9THREAD_PROC compilationThreadProc(void *entryarg)3567{3568//J9JITConfig *jitConfig = (J9JITConfig *)entryarg;3569TR::CompilationInfoPerThread *compInfoPT = (TR::CompilationInfoPerThread *)entryarg;3570J9JITConfig *jitConfig = compInfoPT->getJitConfig();3571J9JavaVM *vm = jitConfig->javaVM;3572J9VMThread *compThread = 0;3573TR::CompilationInfo *compInfo = TR::CompilationInfo::get();3574static bool TR_NoStructuredHandler = feGetEnv("TR_NoStructuredHandler")?1:0;35753576int rc = vm->internalVMFunctions->internalAttachCurrentThread3577(vm, &compThread, NULL,3578J9_PRIVATE_FLAGS_DAEMON_THREAD | J9_PRIVATE_FLAGS_NO_OBJECT |3579J9_PRIVATE_FLAGS_SYSTEM_THREAD | J9_PRIVATE_FLAGS_ATTACHED_THREAD,3580compInfoPT->getOsThread());35813582if (rc != JNI_OK)3583{3584compInfoPT->getCompThreadMonitor()->enter();3585compInfoPT->setCompilationThreadState(COMPTHREAD_ABORT);3586compInfoPT->getCompThreadMonitor()->notifyAll();3587compInfoPT->getCompThreadMonitor()->exit();3588return JNI_ERR;3589}35903591#if defined(LINUX)3592j9thread_set_name(j9thread_self(), "JIT Compilation");3593#endif35943595compInfo->acquireCompMonitor(compThread);3596compInfo->debugPrint(compThread, "+CM\n");3597if (compInfoPT->getCompThreadId() == 0)3598{3599compInfoPT->setCompilationThreadState(COMPTHREAD_ACTIVE);3600compInfo->incNumCompThreadsActive();3601if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))3602{3603TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Created compThread %d as ACTIVE",3604(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), compInfoPT->getCompThreadId());3605}3606}3607else // all other compilation threads should start as suspended3608{3609compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);3610if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))3611{3612TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Created compThread %d as SUSPENDED",3613(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), compInfoPT->getCompThreadId());3614}3615}3616compInfo->releaseCompMonitor(compThread);36173618compInfoPT->getCompThreadMonitor()->enter();3619compInfoPT->setCompilationThread(compThread);36203621compInfoPT->getCompThreadMonitor()->notifyAll(); // just in case main thread is waiting for compThread to appear3622compInfoPT->getCompThreadMonitor()->exit();36233624compInfo->debugPrint(compThread, "\tCompilation Thread attached to the VM\n");36253626compInfo->debugPrint(compThread, "\tCompilation Thread acquiring compilation monitor\n");3627compInfo->acquireCompMonitor(compThread);36283629// It is possible that the shutdown signal came before this thread has had the time3630// to become fully initialized. If that's the case, the state will appear as STOPPING3631// instead of UNINITIALIZED. This can happen when we destroy the cache; the java app3632// starts and finishes immediately3633if (compInfoPT->getCompilationThreadState() == COMPTHREAD_SIGNAL_TERMINATE)3634{3635compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPING);3636// Release the monitor before calling DetachCurrentThread to avoid deadlock3637compInfo->releaseCompMonitor(compThread);3638if (compThread)3639vm->internalVMFunctions->DetachCurrentThread((JavaVM *) vm);36403641// Re-acquire the monitor3642compInfo->acquireCompMonitor(compThread);3643compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPED);3644compInfo->getCompilationMonitor()->notify();36453646j9thread_exit((J9ThreadMonitor*)((TR::Monitor *)compInfo->getCompilationMonitor())->getVMMonitor());36473648return 0; // unreachable3649}36503651PORT_ACCESS_FROM_VMC(compThread);3652IDATA result;36533654#if defined(J9VM_PORT_SIGNAL_SUPPORT)3655if (!TR_NoStructuredHandler)3656{3657/* copied the flags from vmthread.c: note that for the JIT we are not really3658interested in continuing. We are installing the handler merely to get3659support for crash dumps */3660U_32 flags = J9PORT_SIG_FLAG_SIGALLSYNC | J9PORT_SIG_FLAG_MAY_CONTINUE_EXECUTION;3661compThread->gpProtected = 1;36623663I_32 sig_result = j9sig_protect((j9sig_protected_fn)protectedCompilationThreadProc, compInfoPT,3664vm->internalVMFunctions->structuredSignalHandler, compThread,3665flags, (UDATA*)&result);3666if (sig_result != 0)3667{3668result = JNI_ERR;3669}3670}3671else3672#endif3673result = protectedCompilationThreadProc(privatePortLibrary, compInfoPT);36743675j9thread_exit((J9ThreadMonitor*)((TR::Monitor *)compInfo->getCompilationMonitor())->getVMMonitor());36763677return result;3678}36793680#if defined(LINUX)3681#include "sched.h"3682#endif36833684IDATA J9THREAD_PROC protectedCompilationThreadProc(J9PortLibrary *, TR::CompilationInfoPerThread*compInfoPT/*void *vmthread*/)3685{3686J9VMThread * compThread = compInfoPT->getCompilationThread();//(J9VMThread *) vmthread;3687J9JavaVM * vm = compThread->javaVM;3688TR::CompilationInfo * compInfo = TR::CompilationInfo::get();36893690//TODO: decide if the compilation budget should be per thread or not3691compInfo->setCompBudgetSupport(TR::Options::_compilationBudget > 0 &&3692compInfo->asynchronousCompilation() &&3693TR::Compiler->target.numberOfProcessors() < 4 &&3694j9thread_get_cpu_time(j9thread_self()) >= 0); // returns negative value if not supported36953696compInfo->setIdleThreshold(IDLE_THRESHOLD/TR::Compiler->target.numberOfProcessors());369736983699#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT3700if ( vm->javaOffloadSwitchOnWithReasonFunc != NULL )3701(* vm->javaOffloadSwitchOnWithReasonFunc)(compThread, J9_JNI_OFFLOAD_SWITCH_JIT_COMPILATION_THREAD);3702#endif37033704#if defined(WINDOWS)3705// affinity to proc 037063707/*3708if (TR::Options::getCmdLineOptions()->getOption(TR_CummTiming) ||3709TR::Options::getCmdLineOptions()->getOption(TR_Timing) ||3710TR::Options::getCmdLineOptions()->getOption(TR_EnableCompYieldStats))3711setThreadAffinity(j9thread_get_handle(j9thread_self())); // otherwise we get bad numbers3712*/3713if (TR::Options::_compThreadAffinityMask)3714{3715uintptr_t affinityMask = TR::Options::_compThreadAffinityMask;3716int32_t numBitsSetInMask = populationCount(affinityMask);3717int32_t bitNumberToSet = compInfoPT->getCompThreadId() % numBitsSetInMask;3718uintptr_t myMask = 0x1;3719int32_t oneBits = 0;3720for (int32_t k = 0; k < 8*sizeof(uintptr_t); k++, myMask <<= 1)3721{3722if (!(affinityMask & myMask))3723continue; // jump over bits that are 03724// I found a bit that is set3725if (oneBits == bitNumberToSet)3726break;3727oneBits++;3728}3729setThreadAffinity(j9thread_get_handle(j9thread_self()), myMask);3730}3731#elif defined(LINUX) && !defined(J9ZTPF)37323733// affinity to proc 03734if (TR::Options::_compThreadAffinityMask)3735{3736cpu_set_t cpuMask;3737CPU_ZERO(&cpuMask);3738UDATA mask = TR::Options::_compThreadAffinityMask;37393740for (int cpuID=0; mask; cpuID++,mask>>=1)3741{3742if (mask & 1)3743CPU_SET(cpuID, &cpuMask);3744}37453746if (sched_setaffinity(0, sizeof(cpuMask), &cpuMask) < 0)3747// if (pthread_setaffinity_np(hThread, sizeof(cpuMask), &cpuMask) < 0)3748{3749perror("Error setting affinity");3750}3751else3752{3753//printf("Successfully set affinity of comp thread!\n");3754}3755}37563757#endif3758compInfoPT->run();3759compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPING);37603761compInfo->debugPrint(compThread, "\tstopping compilation thread loop\n");37623763// print time spent in compilation thread (may work reliably only on Windows)3764static char * printCompTime = feGetEnv("TR_PrintCompTime");3765if (printCompTime)3766{3767fprintf(stderr, "Time spent in compilation thread =%u ms\n",3768(unsigned)(j9thread_get_self_cpu_time(j9thread_self())/1000000));3769}3770if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))3771{3772TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"Time spent in compilation thread =%u ms",3773(unsigned)(j9thread_get_self_cpu_time(j9thread_self())/1000000));3774}37753776if (TR::Options::isAnyVerboseOptionSet())3777{3778TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Stopping compilation thread, vmThread pointer %p, thread ID %d", compThread, compInfoPT->getCompThreadId());3779}37803781#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT3782if ( vm->javaOffloadSwitchOffWithReasonFunc != NULL )3783(* vm->javaOffloadSwitchOffWithReasonFunc)(compThread, J9_JNI_OFFLOAD_SWITCH_JIT_COMPILATION_THREAD);3784#endif378537863787// Release the monitor before calling DetachCurrentThread to avoid deadlock3788compInfo->releaseCompMonitor(compThread);3789if (compThread)3790vm->internalVMFunctions->DetachCurrentThread((JavaVM *) vm);37913792// Re-acquire the monitor and signal the shutdown thread3793compInfo->acquireCompMonitor(compThread);3794compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPED);3795compInfo->getCompilationMonitor()->notify();3796//compInfoPT->setCompilationThread(0);3797return 0;3798}37993800#if defined(J9VM_OPT_JITSERVER)3801JITServer::ServerStream *3802TR::CompilationInfoPerThread::getStream()3803{3804return (_methodBeingCompiled) ? _methodBeingCompiled->_stream : NULL;3805}3806#endif /* defined(J9VM_OPT_JITSERVER) */38073808void3809TR::CompilationInfoPerThread::run()3810{3811#if defined(J9VM_OPT_JITSERVER)3812TR::compInfoPT = this; // set the thread_local pointer to this object on first run3813#endif3814for (3815CompilationThreadState threadState = getCompilationThreadState();3816threadState != COMPTHREAD_SIGNAL_TERMINATE;3817threadState = getCompilationThreadState()3818)3819{3820switch (threadState)3821{3822case COMPTHREAD_ACTIVE:3823{3824processEntries();3825break;3826}3827case COMPTHREAD_SIGNAL_WAIT:3828{3829waitForWork();3830break;3831}3832case COMPTHREAD_SIGNAL_SUSPEND:3833{3834doSuspend();3835break;3836}3837default:3838{3839TR_ASSERT(false, "No other state possible here %d\n", getCompilationThreadState());3840break;3841}3842}3843}3844}38453846void3847TR::CompilationInfoPerThread::waitForWork()3848{3849TR::CompilationInfo * compInfo = getCompilationInfo();3850J9VMThread * compThread = getCompilationThread();3851compInfo->debugPrint(compThread, "\tcompilation thread waiting for work\n");3852compInfo->debugPrint(compThread, "wait-CM\n");3853compInfo->incNumCompThreadsJobless();3854setLastTimeThreadWentToSleep(compInfo->getPersistentInfo()->getElapsedTime());3855setCompilationThreadState(COMPTHREAD_WAITING);3856compInfo->waitOnCompMonitor(compThread);3857if (getCompilationThreadState() == COMPTHREAD_WAITING)3858{3859/*3860* If we were signaled to suspend or stop,3861* we need to make sure to not lose that information.3862*/3863setCompilationThreadState(COMPTHREAD_ACTIVE);3864}3865compInfo->decNumCompThreadsJobless();3866compInfo->debugPrint(compThread, "+CM\n");3867}38683869void3870TR::CompilationInfoPerThread::doSuspend()3871{3872_compInfo.setSuspendThreadDueToLowPhysicalMemory(false);3873getCompThreadMonitor()->enter();3874setCompilationThreadState(COMPTHREAD_SUSPENDED);3875_compInfo.releaseCompMonitor(getCompilationThread()); // release the queue monitor before waiting3876setLastTimeThreadWasSuspended(_compInfo.getPersistentInfo()->getElapsedTime());3877setVMThreadNameWithFlag(getCompilationThread(), getCompilationThread(), getSuspendedThreadName(), 1);3878getCompThreadMonitor()->wait(); // wait here until someone notifies us3879setVMThreadNameWithFlag(getCompilationThread(), getCompilationThread(), getActiveThreadName(), 1);3880getCompThreadMonitor()->exit();3881_compInfo.acquireCompMonitor(getCompilationThread());3882}38833884J9::J9SegmentCache3885TR::CompilationInfoPerThread::initializeSegmentCache(J9::J9SegmentProvider &segmentProvider)3886{3887#if defined(J9VM_OPT_JITSERVER)3888if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() != JITServer::CLIENT)3889#endif /* defined(J9VM_OPT_JITSERVER) */3890{3891try3892{3893J9::J9SegmentCache segmentCache(1 << 24, segmentProvider);3894return segmentCache;3895}3896catch (const std::bad_alloc &allocationFailure)3897{3898if (TR::Options::getVerboseOption(TR_VerbosePerformance))3899{3900TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Failed to initialize segment cache of size 1 << 24");3901}3902}3903}3904try3905{3906J9::J9SegmentCache segmentCache(1 << 21, segmentProvider);3907return segmentCache;3908}3909catch (const std::bad_alloc &allocationFailure)3910{3911if (TR::Options::getVerboseOption(TR_VerbosePerformance))3912{3913TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Failed to initialize segment cache of size 1 << 21");3914}3915}3916J9::J9SegmentCache segmentCache(1 << 16, segmentProvider);3917return segmentCache;3918}39193920void3921TR::CompilationInfoPerThread::processEntries()3922{3923if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))3924{3925TR_VerboseLog::writeLineLocked(3926TR_Vlog_DISPATCH,3927"Starting to process queue entries. compThreadID=%d state=%d Q_SZ=%d Q_SZI=%d QW=%d\n",3928getCompThreadId(),3929getCompilationThreadState(),3930_compInfo.getMethodQueueSize(),3931_compInfo.getNumQueuedFirstTimeCompilations(),3932_compInfo.getQueueWeight()3933);3934}3935// Possible scenarios here3936// 1. We take a method from queue and compile it3937// 2. We refrain to take a method from queue because that means two simultaneous compilations --> wait to be notified3938// 3. We refrain to take a method from queue because compilation consumes too much CPU.3939// 3.1 If there is another active comp thread, then suspend this one. The activation should be avoided in this situation3940// 3.2 If this is the last active comp thread, wait on the comp monitor timed.3941// Note: the diagnostic thread must not wait.3942TR::CompilationInfo *compInfo = getCompilationInfo();3943J9VMThread * compThread = getCompilationThread();3944try3945{3946J9::SegmentAllocator scratchSegmentAllocator(MEMORY_TYPE_JIT_SCRATCH_SPACE | MEMORY_TYPE_VIRTUAL, *_jitConfig->javaVM);3947J9::J9SegmentCache scratchSegmentCache(initializeSegmentCache(scratchSegmentAllocator).ref());3948while (getCompilationThreadState() == COMPTHREAD_ACTIVE)3949{3950TR::CompilationInfo::TR_CompThreadActions compThreadAction = TR::CompilationInfo::UNDEFINED_ACTION;3951TR_MethodToBeCompiled *entry = compInfo->getNextMethodToBeCompiled(this, _previousCompilationThreadState == COMPTHREAD_WAITING, &compThreadAction);3952switch (compThreadAction)3953{3954case TR::CompilationInfo::PROCESS_ENTRY:3955{3956// Compilation request extracted; go work on it3957TR_ASSERT(entry, "Attempting to process NULL entry");3958processEntry(*entry, scratchSegmentCache);3959break;3960}3961case TR::CompilationInfo::GO_TO_SLEEP_EMPTY_QUEUE:3962{3963// This compilation thread goes to sleep because there is no more work to do3964if (isDiagnosticThread() && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump))3965TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "Diagnostic thread encountered an empty queue");39663967setCompilationThreadState(COMPTHREAD_WAITING);3968setLastTimeThreadWentToSleep(compInfo->getPersistentInfo()->getElapsedTime());3969int64_t waitTimeMillis = 256;3970intptr_t monitorStatus = compInfo->waitOnCompMonitorTimed(compThread, waitTimeMillis, 0);3971if (getCompilationThreadState() == COMPTHREAD_WAITING)3972{3973/*3974* A status of 0 indicates that 'the monitor has been waited on, notified, and reobtained.'3975*/3976if (monitorStatus == 0)3977/*3978* If we were signaled to suspend or stop,3979* we need to make sure to not lose that information.3980*/3981{3982setCompilationThreadState(COMPTHREAD_ACTIVE);3983}3984else3985{3986TR_ASSERT(monitorStatus == J9THREAD_TIMED_OUT, "Unexpected monitor state");3987// It's possible that a notification was sent just after the3988// timeout expired. Hence, if something was added to the compilation3989// queue we must attempt to process it3990if (_compInfo.getMethodQueueSize() > 0)3991{3992setCompilationThreadState(COMPTHREAD_ACTIVE);3993}3994else3995{3996setCompilationThreadState(COMPTHREAD_SIGNAL_WAIT);3997}3998if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))3999{4000TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "compThreadID=%d woke up after timeout on compMonitor\n", getCompThreadId());4001}4002}4003}4004break;4005}4006case TR::CompilationInfo::GO_TO_SLEEP_CONCURRENT_EXPENSIVE_REQUESTS:4007setCompilationThreadState(COMPTHREAD_SIGNAL_WAIT);4008break;40094010case TR::CompilationInfo::SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT:4011case TR::CompilationInfo::SUSPEND_COMP_THREAD_EMPTY_QUEUE:4012TR_ASSERT(compInfo->getNumCompThreadsActive() > 1, "Should not suspend the last active compilation thread: %d\n", compInfo->getNumCompThreadsActive());4013setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);4014compInfo->decNumCompThreadsActive();4015if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))4016{4017TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Suspending compThread %d due to %s Qweight=%d active=%d overallCompCpuUtil=%d",4018(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),4019getCompThreadId(),4020compThreadAction == TR::CompilationInfo::SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT ? "exceeding CPU entitlement" : "empty queue",4021compInfo->getQueueWeight(),4022compInfo->getNumCompThreadsActive(),4023compInfo->getOverallCompCpuUtilization());4024}4025break;40264027case TR::CompilationInfo::THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT:4028{4029TR_ASSERT(compInfo->getNumCompThreadsActive() <= 1, "Throttling when we have several comp threads active: %d\n", compInfo->getNumCompThreadsActive());4030int32_t sleepTimeMs = compInfo->computeCompThreadSleepTime(getLastCompilationDuration());4031if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))4032{4033TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u compThread %d sleeping %d ms due to throttling Qweight=%d active=%d overallCompCpuUtil=%d",4034(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),4035getCompThreadId(),4036sleepTimeMs,4037compInfo->getQueueWeight(),4038compInfo->getNumCompThreadsActive(),4039compInfo->getOverallCompCpuUtilization());4040}4041compInfo->debugPrint(compThread, "\tcompilation thread waiting some time\n");4042compInfo->debugPrint(compThread, "wait-CM\n");4043// Don't increment jobless here because there is work to be done4044// The thread will wake up after specified time and process the request at front of queue4045setCompilationThreadState(COMPTHREAD_WAITING);4046setLastTimeThreadWentToSleep(compInfo->getPersistentInfo()->getElapsedTime());4047intptr_t monitorStatus = compInfo->waitOnCompMonitorTimed(compThread, sleepTimeMs, 0);4048if (getCompilationThreadState() == COMPTHREAD_WAITING)4049{4050/*4051* If we were signaled to suspend or stop,4052* we need to make sure to not lose that information.4053*/4054setCompilationThreadState(COMPTHREAD_ACTIVE);4055}4056compInfo->debugPrint(compThread, "+CM\n");4057}4058break;40594060default:4061TR_ASSERT_FATAL(false, "Invalid action: %d\n", compThreadAction);4062break;4063}4064}4065}4066catch (const std::bad_alloc &allocationFailure)4067{4068TR_ASSERT(!TR::Compiler->host.is64Bit() ,"Virtual memory exhaustion is unexpected on 64 bit platforms.");4069compInfo->setRampDownMCT();4070if (compInfo->getNumCompThreadsActive() > 1)4071{4072if (compilationThreadIsActive())4073{4074setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);4075compInfo->decNumCompThreadsActive();4076if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerbosePerformance))4077{4078TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Suspending compilation thread %d due to insufficient resources",4079(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), getCompThreadId());4080}4081}4082}4083else4084{4085/*4086* Even the last compilation thread could not allocate an initial segment4087* Memory is hopelessly fragmented: stop all compilations4088*/4089compInfo->getPersistentInfo()->setDisableFurtherCompilation(true);4090if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerbosePerformance, TR_VerboseCompFailure))4091{4092TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Disable further compilation due to OOM while processing compile entries", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime());4093}4094compInfo->purgeMethodQueue(compilationVirtualAddressExhaustion);4095// Must change the state to prevent an infinite loop4096// Change it to COMPTHREAD_SIGNAL_WAIT because the compilation queue is empty4097setCompilationThreadState(COMPTHREAD_SIGNAL_WAIT);4098}4099}4100#if defined(J9VM_OPT_JITSERVER)4101static bool enableJITServerPerCompConn = feGetEnv("TR_EnableJITServerPerCompConn") ? true : false;4102if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && !enableJITServerPerCompConn)4103{4104JITServer::ClientStream *client = getClientStream();4105if (client)4106{4107// Inform the server that client is closing the connection with a connectionTerminate message4108if (JITServerHelpers::isServerAvailable())4109{4110try4111{4112client->writeError(JITServer::MessageType::connectionTerminate, 0 /* placeholder */);4113}4114catch (const JITServer::StreamFailure &e)4115{4116if (TR::Options::getVerboseOption(TR_VerboseJITServer))4117TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "JITServer StreamFailure when sending connectionTerminate: %s", e.what());4118}4119}41204121client->~ClientStream();4122TR_Memory::jitPersistentFree(client);4123setClientStream(NULL);4124}4125}4126#endif /* defined(J9VM_OPT_JITSERVER) */4127}41284129void4130TR::CompilationInfoPerThread::processEntry(TR_MethodToBeCompiled &entry, J9::J9SegmentProvider &scratchSegmentProvider)4131{4132TR::CompilationInfo *compInfo = getCompilationInfo();4133J9VMThread *compThread = getCompilationThread();4134TR::IlGeneratorMethodDetails & details = entry.getMethodDetails();4135J9Method *method = details.getMethod();41364137setMethodBeingCompiled(&entry); // must have compilation monitor41384139// Increase main queue weight while still holding compilation monitor4140if (entry._reqFromSecondaryQueue || entry._reqFromJProfilingQueue)4141compInfo->increaseQueueWeightBy(entry._weight);41424143compInfo->printQueue();41444145entry._compInfoPT = this; // need to know which comp thread is handling this request41464147// update the last time the compilation thread had to do something.4148compInfo->setLastReqStartTime(compInfo->getPersistentInfo()->getElapsedTime());41494150// Update how many compilation threads are working on hot/scorching methods4151if (entry._weight >= TR::Options::_expensiveCompWeight)4152{4153compInfo->incNumCompThreadsCompilingHotterMethods(); // must be called with compMonitor in hand4154entry._hasIncrementedNumCompThreadsCompilingHotterMethods = true;4155}41564157// Now we no longer need the monitor - it is not held during compilation4158//4159compInfo->debugPrint(compThread, "\tcompilation thread releasing monitor before compile\n");4160compInfo->debugPrint(compThread, "-CM\n");4161compInfo->releaseCompMonitor(compThread);41624163// We cannot examine the fields of method because it might have been unloaded4164// First we need to acquire VM access or prevent unloading4165//4166// Acquire VM access4167//4168acquireVMAccessNoSuspend(compThread);4169compInfo->debugPrint(compThread, "+VMacc\n");41704171// If GC is in the middle of a duty cycle, wait for the cycle to finish4172// This is for RealTime only. Note that we need to perform this operation with VMAccess4173// in hand. Otherwise, after the comp thread has found that GC is not active but before4174// it acquires VM access, the GC could start a cycle and decide to unload a method4175// which will be later pinned by the compilation thread. The problem is that in realtime4176// GC does not execute all the work atomically. It may decide to unload some classes now,4177// then pause for a while, then coming back and doing the actual unloading without4178// verifying again that the class has been pinned4179//4180if (TR::Options::getCmdLineOptions()->realTimeGC())4181waitForGCCycleMonitor(true); // the parameter indicates that the thread has VM access41824183if (!shouldPerformCompilation(entry))4184{4185if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))4186{4187TR_VerboseLog::writeLineLocked(4188TR_Vlog_DISPATCH,4189"Rejecting compilation request for j9m=%p. unloaded=%d fromJPQ=%d",4190entry.getMethodDetails().getMethod(), entry._unloadedMethod, entry._reqFromJProfilingQueue);4191}41924193// Acquire compilation monitor4194//4195compInfo->debugPrint(compThread, "\tacquiring compilation monitor\n");4196compInfo->acquireCompMonitor(compThread);4197compInfo->debugPrint(compThread, "+CM\n");41984199// Release VM access4200//4201compInfo->debugPrint(compThread, "\tcompilation thread releasing VM access\n");4202releaseVMAccess(compThread);4203compInfo->debugPrint(compThread, "-VMacc\n");4204// decrease the queue weight4205compInfo->decreaseQueueWeightBy(entry._weight);4206// Update how many compilation threads are working on hot/scorching methods4207if (entry._hasIncrementedNumCompThreadsCompilingHotterMethods)4208compInfo->decNumCompThreadsCompilingHotterMethods();42094210// put the request back into the pool4211//4212setMethodBeingCompiled(NULL); // Must have the compQmonitor4213compInfo->recycleCompilationEntry(&entry);42144215// there are no threads to be notified because either this is an async request4216// or a sync request where classes have been redefined in which case the jit hook will to the signalling4217return;4218}42194220// Pin the class of the method being compiled to prevent it from being unloaded4221//4222// This conversion is safe. The macro J9VM_J9CLASS_TO_HEAPCLASS will not make a conversion if Classes on Heap is not enabled.4223jobject classObject = NULL;4224if (!entry.isOutOfProcessCompReq())4225classObject = compThread->javaVM->internalVMFunctions->j9jni_createLocalRef((JNIEnv*)compThread, J9VM_J9CLASS_TO_HEAPCLASS(details.getClass()));42264227// Do the hack for newInstance thunks4228// Also make the method appear as interpreted, otherwise we might want to access recompilation info4229// FIXME: do this more elegantly4230//4231//TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();4232if (details.isNewInstanceThunk())4233{4234J9::NewInstanceThunkDetails &newInstanceDetails = static_cast<J9::NewInstanceThunkDetails &>(details);4235J9Class *classForNewInstance = newInstanceDetails.classNeedingThunk();4236TR::CompilationInfo::setJ9MethodExtra(method,(uintptr_t)classForNewInstance | J9_STARTPC_NOT_TRANSLATED);4237}42384239#ifdef STATS4240statQueueSize.update(compInfo->getMethodQueueSize());4241#endif4242TR_ASSERT(entry._optimizationPlan, "Must have an optimization plan");42434244// The server should not adjust the opt plan requested by the client.4245if (!entry.isOutOfProcessCompReq())4246TR::CompilationController::getCompilationStrategy()->adjustOptimizationPlan(&entry, 0);42474248entry._tryCompilingAgain = false; // this field may be set by compile()42494250// The following call will return with compilation monitor and the4251// queue slot (entry) monitor in hand4252//4253void *startPC = compile(compThread, &entry, scratchSegmentProvider);42544255// We have acquired VM access above and will be releasing it below. It is possible however that during the4256// compilation process in the above `compile(...)` call we have released VM access and have subsequently4257// crashed or asserted. In such a scenario the JitDump process will have started and queued the method4258// for recompilation with a custom signal handler to catch the crash/assertion and return. The JitDump4259// compilation will have hopefully crashed/asserted in the same place as the original compilation, and4260// thus we will not be holding VM access at that point. This means we will return from the above call to4261// `compile(...)` without holding VM access, and below we will attempt to call `j9jni_deleteLocalRef` to4262// unpin the class. The `j9jni_deleteLocalRef` function has a requirement that we hold VM access otherwise4263// it will assert. We do not want to assert, as that will end up calling `abort()` and the JitDump process4264// will not complete, nor will any dump handlers following JitDump.4265if ((compThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) == 0)4266{4267TR_ASSERT_FATAL(isDiagnosticThread(), "A compilation thread has finished a compilation but does not hold VM access");42684269acquireVMAccessNoSuspend(compThread);4270compInfo->debugPrint(compThread, "+VMacc\n");4271}42724273// Unpin the class4274if (!entry.isOutOfProcessCompReq())4275compThread->javaVM->internalVMFunctions->j9jni_deleteLocalRef((JNIEnv*)compThread, classObject);42764277// Update how many compilation threads are working on hot/scorching methods4278if (entry._hasIncrementedNumCompThreadsCompilingHotterMethods)4279compInfo->decNumCompThreadsCompilingHotterMethods();42804281entry._newStartPC = startPC;42824283if (startPC && startPC != entry._oldStartPC)4284{4285compInfo->debugPrint("\tcompilation succeeded for method", details, compThread);4286// Add upgrade request to secondary queue if we downgraded, this is not GCR and method4287// looks important enough that an upgrade is justified4288if (entry._compErrCode == compilationOK)4289{4290if (entry._optimizationPlan->shouldAddToUpgradeQueue())4291{4292// clone this request, adjust its _oldStartPC to match the _newStartPC for the4293// this request, and insert it in the low upgrade queue4294compInfo->getLowPriorityCompQueue().addUpgradeReqToLPQ(getMethodBeingCompiled(), TR_MethodToBeCompiled::REASON_UPGRADE);4295#ifdef STATS4296fprintf(stderr, "Downgraded request will be added to upgrade queue\n");4297#endif4298}4299#if defined(J9VM_OPT_JITSERVER)4300else if (entry.shouldUpgradeOutOfProcessCompilation())4301{4302// If it's a local cold downgraded compilation, add an upgrade request to the LPQ, hoping that4303// the server will become available at some point in the future4304if (TR::Options::isAnyVerboseOptionSet(4305TR_VerboseJITServer,4306TR_VerboseCompilationDispatch,4307TR_VerbosePerformance,4308TR_VerboseCompFailure))4309TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "t=%6u Buffering an upgrade request into the LPQ: j9method=%p",4310(uint32_t) compInfo->getPersistentInfo()->getElapsedTime(),4311entry.getMethodDetails().getMethod());4312compInfo->getLowPriorityCompQueue().addUpgradeReqToLPQ(getMethodBeingCompiled(), TR_MethodToBeCompiled::REASON_SERVER_UNAVAILABLE);4313}4314#endif4315}4316}4317else // compilation failure4318{4319compInfo->debugPrint("\tcompilation failed for method", details, compThread);4320}4321// Update statistics regarding the compilation status (including compilationOK)4322compInfo->updateCompilationErrorStats((TR_CompilationErrorCode)entry._compErrCode);43234324// Copy this because it is needed later and entry may be recycled4325bool tryCompilingAgain = entry._tryCompilingAgain;43264327if (entry._tryCompilingAgain)4328{4329// We got interrupted during the compile, and want to requeue this compilation request4330//4331TR_ASSERT(!entry._unloadedMethod, "For unloaded methods, it should not be possible to try compiling again");43324333CompilationPriority oldPriority = (CompilationPriority)entry._priority;4334if (oldPriority <= CP_ASYNC_MAX)4335{4336oldPriority = CP_ASYNC_MAX;4337// While we increased the priority of this request, there might be a SYNC request in the queue4338// which has higher priority. In that case we should remove the possible reservation of a dataCache4339if (reservedDataCache() && compInfo->getMethodQueue() && compInfo->getMethodQueue()->_priority >= CP_ASYNC_MAX)4340{4341TR_DataCacheManager::getManager()->makeDataCacheAvailable(reservedDataCache());4342setReservedDataCache(NULL);4343}4344}4345else4346{4347oldPriority = CP_SYNC_BELOW_MAX;4348}43494350entry._priority = oldPriority;4351--entry._compilationAttemptsLeft;4352entry._hasIncrementedNumCompThreadsCompilingHotterMethods = false; // re-initialize4353entry._GCRrequest = false; // pretend it's not GCR4354entry._reqFromSecondaryQueue = TR_MethodToBeCompiled::REASON_NONE; // we are going to put this into the main queue, so entry is not coming from LPQ anymore4355// TODO: the following is needed or otherwise we will wrongly increase the Q weight when extracting it again4356// However, we lose our _reqFromJProfilingQueue flag so we will not insert profiling trees4357// We need some other form of flag, maybe in the optimization plan or4358// retrials of compilations from JPQ are not going to work correctly4359entry._reqFromJProfilingQueue = false;4360#if defined(J9VM_OPT_JITSERVER)4361entry.unsetRemoteCompReq(); // remote compilation decisions do not carry over from one retrial to the next4362#endif43634364compInfo->debugPrint("\trequeueing interrupted compilation request", details, compThread);43654366// After releasing the monitors and vm access below, we will loop back to the head of the loop, and retry the4367// compilation. Do not put the request back into the pool, instead requeue.4368//4369requeue();4370setMethodBeingCompiled(NULL); // Must have the compQmonitor4371}4372else // compilation will not be retried4373{4374TR_OptimizationPlan::freeOptimizationPlan(entry._optimizationPlan); // we no longer need the optimization plan4375// decrease the queue weight4376compInfo->decreaseQueueWeightBy(entry._weight);4377// Put the request back into the pool4378setMethodBeingCompiled(NULL);4379compInfo->recycleCompilationEntry(&entry);43804381// notify the sleeping threads that the compilation request has been served4382// (either it succeeded or it failed and we are not going to requeue).4383//4384compInfo->debugPrint(compThread, "\tnotify sleeping threads that the compilation is done\n");4385entry.getMonitor()->notifyAll();4386compInfo->debugPrint(compThread, "ntfy-", &entry);4387}43884389compInfo->printQueue();43904391// Release the queue slot monitor4392//4393compInfo->debugPrint(compThread, "\tcompilation thread releasing queue slot monitor\n");4394compInfo->debugPrint(compThread, "-AM-", &entry);4395entry.releaseSlotMonitor(compThread);43964397// At this point we should always have VMAccess4398// We should always have the compilation monitor4399// we should never have classUnloadMonitor44004401// Release VM access4402//4403compInfo->debugPrint(compThread, "\tcompilation thread releasing VM access\n");4404releaseVMAccess(compThread);4405compInfo->debugPrint(compThread, "-VMacc\n");4406// We can suspend this thread if too many are active4407if (4408!isDiagnosticThread() // must not be reserved for log4409&& compInfo->getNumCompThreadsActive() > 1 // we should have at least one active besides this one4410&& compilationThreadIsActive() // We haven't already been signaled to suspend or terminate4411&& (4412compInfo->getRampDownMCT() // force to have only one thread active4413|| compInfo->getSuspendThreadDueToLowPhysicalMemory()4414|| (4415!tryCompilingAgain4416/*&& compInfoPT->getCompThreadId() != 0*/4417&& TR::Options::getCmdLineOptions()->getOption(TR_SuspendEarly)4418&& compInfo->getQueueWeight() < TR::CompilationInfo::getCompThreadSuspensionThreshold(compInfo->getNumCompThreadsActive())4419)4420#if defined(J9VM_OPT_JITSERVER)4421|| (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT4422&& compInfo->getCompThreadActivationPolicy() == JITServer::CompThreadActivationPolicy::SUSPEND) // keep suspending threads until server space frees up4423#endif4424)4425)4426{4427// Suspend this thread4428setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);4429compInfo->decNumCompThreadsActive();4430if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))4431{4432TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Suspend compThread %d Qweight=%d active=%d %s %s %s",4433(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),4434getCompThreadId(),4435compInfo->getQueueWeight(),4436compInfo->getNumCompThreadsActive(),4437compInfo->getRampDownMCT() ? "RampDownMCT" : "",4438compInfo->getSuspendThreadDueToLowPhysicalMemory() ? "LowPhysicalMem" : "",4439#if defined(J9VM_OPT_JITSERVER)4440compInfo->getCompThreadActivationPolicy() == JITServer::CompThreadActivationPolicy::SUSPEND ? "ServerLowPhysicalMemOrHighThreadCount" :4441#endif4442""4443);4444}4445// If the other remaining active thread(s) are sleeping (maybe because4446// we wanted to avoid two concurrent hot requests) we need to wake them4447// now as a preventive measure. Worst case scenario they will go back to sleep4448if (compInfo->getNumCompThreadsJobless() > 0)4449{4450compInfo->getCompilationMonitor()->notifyAll();4451if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))4452{4453TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u compThread %d notifying other sleeping comp threads. Jobless=%d",4454(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),4455getCompThreadId(),4456compInfo->getNumCompThreadsJobless());4457}4458}4459if (tryCompilingAgain)4460{4461// For compilation retrial we normally keep the data cache4462// Because another thread may handle the request we have to unreserve any data cache4463if (reservedDataCache())4464{4465TR_DataCacheManager::getManager()->makeDataCacheAvailable(reservedDataCache());4466setReservedDataCache(NULL);4467// TODO: write a message into the trace buffer because this is a corner case4468}4469}4470}4471else // We will not suspend this thread4472{4473// If the low memory flag was set but there was no additional comp thread4474// to suspend, we must clear the flag now4475if (compInfo->getSuspendThreadDueToLowPhysicalMemory() &&4476compInfo->getNumCompThreadsActive() < 2)4477compInfo->setSuspendThreadDueToLowPhysicalMemory(false);4478}4479}44804481bool4482TR::CompilationInfoPerThread::shouldPerformCompilation(TR_MethodToBeCompiled &entry)4483{4484if (entry.isOutOfProcessCompReq())4485return true;4486TR::CompilationInfo *compInfo = getCompilationInfo();4487TR::IlGeneratorMethodDetails &details = entry.getMethodDetails();4488J9Method *method = details.getMethod();44894490// Do not compile unloaded methods4491if (entry._unloadedMethod)4492return false;44934494// Do not compile replaced methods4495if ((TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR) || TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug))4496&& details.getClass() && J9_IS_CLASS_OBSOLETE(details.getClass()))4497return false;449844994500if (entry._reqFromSecondaryQueue)4501{4502// This is a request coming from the low priority queue4503bool doCompile = false;45044505// Determine if this was a fast comp req for an interpreted method4506if (!entry._oldStartPC)4507{4508// Set method->extra = J9_JIT_QUEUED_FOR_COMPILATION4509// and stimulate a compilation (if conditions are right)4510if (!(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccNative)) // never change the extra field of a native method4511{4512if (!TR::CompilationInfo::isCompiled(method)) // Don't touch methods compiled through other means4513{4514if (compInfo->getInvocationCount(method) > 0) // Valid invocation counter4515{4516// FIXME: is this safe here?4517// What if the method is about to be compiled?4518compInfo->setJ9MethodVMExtra(method, J9_JIT_QUEUED_FOR_COMPILATION);4519doCompile = true;4520}4521}4522else // compiled body4523{4524compInfo->getLowPriorityCompQueue().incStatsBypass(); // statistics4525}4526}4527// stop tracking this method in the hashtable4528if (compInfo->getLowPriorityCompQueue().isTrackingEnabled())4529compInfo->getLowPriorityCompQueue().stopTrackingMethod(method);4530}4531else // RE-compilation request from LPQ4532{4533TR_ASSERT(entry._reqFromSecondaryQueue == TR_MethodToBeCompiled::REASON_UPGRADE, "wrong reason for upgrade");4534// This method might have failed compilation or have been rejected due to filters4535void *startPC = TR::CompilationInfo::getPCIfCompiled(method);4536if (startPC)4537{4538// A compilation attempt might have already happened for this method4539// (and failed or succeeded)4540J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(startPC);4541if (!linkageInfo->isBeingCompiled()) // This field is never reset4542{4543// get its level4544TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(startPC);4545// The method might have already been recompiled4546// Or a compilation request might have been attempted and failed. The linkage4547// word could tell us if this body has ever been queued for compilation45484549if (bodyInfo && bodyInfo->getHotness() < warm)4550{4551doCompile = true;4552linkageInfo->setIsBeingRecompiled();4553TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();4554// adjust the level in persistentMethodInfo as well4555methodInfo->setNextCompileLevel(entry._optimizationPlan->getOptLevel(), false);4556// set the reason for recompilation4557methodInfo->setReasonForRecompilation(TR_PersistentMethodInfo::RecompDueToSecondaryQueue);4558}4559}4560else4561{4562compInfo->getLowPriorityCompQueue().incStatsBypass(); // statistics4563}4564}4565else4566{4567// This case corresponds to a situation where we had a downgraded first time compilation4568// into the main queue and an upgrade into the LPQ. The request from the main queue fails4569// and we now have to execute the upgrade.4570// Do not do it4571}4572}4573if (!doCompile)4574return false;4575}4576else if (entry._reqFromJProfilingQueue)4577{4578// We should not compile a request from JProfiling queue if the method has been4579// recompiled since we put this request in the JPQ. Our expectation is that4580// the current startPC is entry->_oldStartPC4581void *startPC = TR::CompilationInfo::getJ9MethodStartPC(method);4582if (startPC != entry._oldStartPC)4583return false;45844585// A compilation request might have been attempted and failed. The linkage4586// word could tell us if this body has ever been queued for compilation4587J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(startPC);4588if (linkageInfo->isBeingCompiled()) // This field is never reset4589return false;4590linkageInfo->setIsBeingRecompiled();4591TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(startPC);4592// bodyInfo must exist because requests from JQP are always recompilations4593TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();4594// set the reason for recompilation4595methodInfo->setReasonForRecompilation(TR_PersistentMethodInfo::RecompDueToJProfiling);4596// adjust the level in persistentMethodInfo as well4597methodInfo->setNextCompileLevel(entry._optimizationPlan->getOptLevel(), false);4598}4599return true;4600}46014602TR_MethodToBeCompiled *4603TR::CompilationInfo::addMethodToBeCompiled(TR::IlGeneratorMethodDetails & details, void *pc,4604CompilationPriority priority, bool async,4605TR_OptimizationPlan *optimizationPlan, bool *queued,4606TR_YesNoMaybe methodIsInSharedCache)4607{4608// Make sure the entry is consistent4609//4610#if DEBUG4611if (pc)4612{4613TR_PersistentMethodInfo* methodInfo = TR::Recompilation::getMethodInfoFromPC(pc);4614if (methodInfo)4615TR_ASSERT(details.getMethod() == (J9Method *)methodInfo->getMethodInfo(), "assertion failure");4616}4617#endif46184619// Add this method to the queue of methods waiting to be compiled.4620TR_MethodToBeCompiled *cur = NULL, *prev = NULL;4621uint32_t queueWeight = 0; // QW4622int32_t numEntries = 0;46234624// See if the method is already in the queue or is already being compiled4625//4626J9VMThread *vmThread = _jitConfig->javaVM->internalVMFunctions->currentVMThread(_jitConfig->javaVM);4627TR_J9VMBase * fe = TR_J9VMBase::get(_jitConfig, vmThread);46284629// search among the threads4630for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)4631{4632TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];4633TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");46344635TR_MethodToBeCompiled *compMethod = curCompThreadInfoPT->getMethodBeingCompiled();4636if (compMethod)4637{4638queueWeight += compMethod->_weight; // QW4639if (compMethod->getMethodDetails().sameAs(details, fe))4640{4641if (!compMethod->_unloadedMethod) // Redefinition; see cmvc 192606 and RTC 368984642{4643// If the priority has increased, use the new priority.4644//4645if (compMethod->_priority < priority)4646compMethod->_priority = priority;4647return compMethod;4648}4649}4650}4651}46524653J9Method *method = details.getMethod();46544655// Ordinary, non-JNI methods that are interpreted have their 'j9method->extra' field4656// set to J9_JIT_QUEUED_FOR_COMPILATION when they are added to the queue4657// Thus, we can skip searching the queue if j9method->extra has another value4658// However, sync compilations do not set method->extra to J9_JIT_QUEUED_FOR_COMPILATION4659bool skipSearchingForDuplicates = false;4660static char *disableSkipSearching = feGetEnv("TR_DisableSkipSearchingForRequestDuplicates");4661if (!disableSkipSearching &&4662pc == 0 && // Interpreted methods4663details.isOrdinaryMethod() &&4664!isJNINative(method) &&4665!(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccNative) &&4666getJ9MethodVMExtra(method) != J9_JIT_QUEUED_FOR_COMPILATION)4667{4668skipSearchingForDuplicates = true;4669}46704671if (skipSearchingForDuplicates)4672{4673// In this case we only have to scan the synchronous requests in the queue4674for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)4675{4676// Stop the search when we finished with sync entries4677if (cur->_priority < CP_SYNC_MIN)4678{4679cur = NULL; // signal that we din't find the entry4680break;4681}4682if (cur->getMethodDetails().sameAs(details, fe))4683break;4684}4685}4686else // Scan the entire queue4687{4688for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)4689{4690numEntries++;4691queueWeight += cur->_weight;4692if (cur->getMethodDetails().sameAs(details, fe))4693break;4694}4695}46964697// NOTE: we do not need to search the methodPool since we cannot reach here if an entry4698// for the compilation of this method is already in the pool. Things are put in the pool4699// after the compilation completes and we have updated the J9Method etc.4700// in which case the compilation is already done and we should not even try to enqueue47014702if (cur)4703{4704if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))4705TR_VerboseLog::writeLineLocked(TR_Vlog_CR,"%p Already present in compilation queue. OldPriority=%x NewPriority=%x entry=%p",4706_jitConfig->javaVM->internalVMFunctions->currentVMThread(_jitConfig->javaVM), cur->_priority, priority, cur);47074708// Method is already in the queue.4709// If the startPC has changed, assume the new one is more recent.4710//4711if (pc)4712cur->_oldStartPC = pc;47134714// If the priority has increased, use the new priority4715//4716if (cur->_priority < priority)4717cur->_priority = priority;4718// If the optimization level is higher, just upgrade4719// (unless the methods has excessive complexity)4720//4721if (cur->_optimizationPlan->getOptLevel() != optimizationPlan->getOptLevel())4722{4723if (cur->_optimizationPlan->getOptLevel() < optimizationPlan->getOptLevel())4724cur->_optimizationPlan->setOptLevel(optimizationPlan->getOptLevel());4725if (pc)4726{4727TR_PersistentMethodInfo *methodInfo = TR::Recompilation::getMethodInfoFromPC(pc);4728if (methodInfo && methodInfo->getNextCompileLevel() != cur->_optimizationPlan->getOptLevel())4729methodInfo->setNextCompileLevel(cur->_optimizationPlan->getOptLevel(), cur->_optimizationPlan->insertInstrumentation());4730}4731}4732// If the position in the queue is still correct, just return4733//4734if (!prev || prev->_priority >= cur->_priority)4735return cur;47364737// Must re-position in the queue4738//4739prev->_next = cur->_next; // take it out of the queue4740}47414742// If method is not yet in the queue prepare the queue entry4743//4744else4745{4746// If we skipped searching, we cannot do the validation checks4747if (!skipSearchingForDuplicates)4748{4749if (queueWeight != _queueWeight) //QW4750{4751if (TR::Options::isAnyVerboseOptionSet())4752TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Discrepancy for queue weight while adding to queue: computed=%u recorded=%u\n", queueWeight, _queueWeight);4753// correction4754_queueWeight = queueWeight;4755}4756if (numEntries != _numQueuedMethods)4757{4758if (TR::Options::isAnyVerboseOptionSet())4759TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Discrepancy for queue size while adding to queue: Before adding numEntries=%d _numQueuedMethods=%d\n", numEntries, _numQueuedMethods);4760TR_ASSERT(false, "Discrepancy for queue size while adding to queue");4761}4762}4763cur = getCompilationQueueEntry();4764if (cur == NULL) // Memory Allocation Failure.4765return NULL;47664767cur->initialize(details, pc, priority, optimizationPlan);4768cur->_jitStateWhenQueued = getPersistentInfo()->getJitState();47694770bool isJNINativeMethodRequest = false;4771if (pc)4772{4773J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(pc);4774#if defined(OSX) && defined(AARCH64)4775pthread_jit_write_protect_np(0);4776#endif4777linkageInfo->setIsBeingRecompiled(); // mark that we try to compile it4778#if defined(OSX) && defined(AARCH64)4779pthread_jit_write_protect_np(1);4780#endif47814782// Update persistentMethodInfo with the level we want to compile to4783//4784TR_PersistentJittedBodyInfo* bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(pc);4785TR_ASSERT(bodyInfo, "We must have bodyInfo because we recompile");4786TR_PersistentMethodInfo* methodInfo = bodyInfo->getMethodInfo(); //TR::Recompilation::getMethodInfoFromPC(pc);4787TR_ASSERT(methodInfo, "We must have methodInfo because we recompile");4788methodInfo->setNextCompileLevel(optimizationPlan->getOptLevel(), optimizationPlan->insertInstrumentation());4789// check if this is an invalidation request and if so increase the appropriate counter4790//4791if (bodyInfo->getIsInvalidated())4792incNumInvRequestsQueued(cur);47934794// Increment this only if recompilations are due to sampling4795if (linkageInfo->isSamplingMethodBody())4796{4797if (methodInfo->getReasonForRecompilation() != TR_PersistentMethodInfo::RecompDueToGCR)4798_intervalStats._numRecompilationsInInterval++;4799else4800incNumGCRRequestsQueued(cur);4801}4802// Should we bump the count of first time compilations?4803// If not, the danger is that there will be many GCR compilations and we enter STEADY state4804}4805else if (details.isOrdinaryMethod()) // ordinary interpreted methods4806{4807isJNINativeMethodRequest = isJNINative(method);4808if (async4809&& (getInvocationCount(method) == 0) // this will filter out JNI natives4810&& !(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccNative)) // Never change the extra field of a native method4811{4812setJ9MethodVMExtra(method, J9_JIT_QUEUED_FOR_COMPILATION);4813}4814_intervalStats._numFirstTimeCompilationsInInterval++;4815_numQueuedFirstTimeCompilations++;4816}4817cur->_entryTime = getPersistentInfo()->getElapsedTime(); // cheaper version4818#if defined(J9VM_INTERP_AOT_RUNTIME_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))4819cur->_methodIsInSharedCache = methodIsInSharedCache;4820#endif4821incrementMethodQueueSize(); // one more method added to the queue4822*queued = true; // set the flag that we added a new request to the queue48234824Trc_JIT_CompRequest(vmThread, method, pc, !async, optimizationPlan->getOptLevel(), (int)priority, _numQueuedMethods);48254826// Increase the queue weight4827uint8_t entryWeight; // must be less than 2564828if (!details.isOrdinaryMethod() || details.isNewInstanceThunk() || isJNINativeMethodRequest)4829entryWeight = THUNKS_WEIGHT; // 14830else if (methodIsInSharedCache == TR_yes && !pc) // first time compilations that are AOT loads4831entryWeight = TR::Options::_weightOfAOTLoad;4832else if (optimizationPlan->getOptLevel() == warm) // most common case first4833{4834// Compilation may be downgraded to cold during classLoadPhase4835// While we cannot anticipate that classLoadPhase will last till the method4836// is extracted from the queue, this is the best estimate4837if (TR::CompilationInfo::isJSR292(method))4838{4839entryWeight = (uint32_t)TR::Options::_weightOfJSR292;4840}4841else if (getPersistentInfo()->isClassLoadingPhase() && !isCompiled(method) &&4842!TR::Options::getCmdLineOptions()->getOption(TR_DontDowngradeToCold) &&4843TR::Options::getCmdLineOptions()->allowRecompilation()) // don't do it for fixed level4844{4845entryWeight = COLD_WEIGHT;4846}4847else4848{4849// Smaller methods are easier to compile4850J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);4851uint32_t methodSize = getMethodBytecodeSize(romMethod);48524853if (methodSize < 8)4854{4855entryWeight = COLD_WEIGHT;4856}4857else4858{4859// Loopless methods are easier to compile4860if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))4861entryWeight = WARM_LOOPY_WEIGHT;4862else4863entryWeight = WARM_LOOPLESS_WEIGHT;4864}4865}4866}4867else if (optimizationPlan->getOptLevel() == cold)4868entryWeight = COLD_WEIGHT;4869else if (optimizationPlan->getOptLevel() >= veryHot)4870entryWeight = VERY_HOT_WEIGHT;4871else if (optimizationPlan->getOptLevel() == hot)4872entryWeight = HOT_WEIGHT;4873else if (optimizationPlan->getOptLevel() == noOpt)4874entryWeight = NOOPT_WEIGHT;4875else4876{4877entryWeight = THUNKS_WEIGHT;4878TR_ASSERT(false, "Unknown hotness level %d\n", optimizationPlan->getOptLevel());4879}48804881// Other tweaks go here: method size, profiling bodies, loopy/loopless, classLoadPhase, sync/async4882cur->_weight = entryWeight;4883increaseQueueWeightBy(entryWeight);48844885if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))4886TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "%p Added entry %p of weight %d to comp queue. Now Q_SZ=%d weight=%d",4887_jitConfig->javaVM->internalVMFunctions->currentVMThread(_jitConfig->javaVM), cur, entryWeight, getMethodQueueSize(), getQueueWeight());48884889// Examine if we need to activate a new thread4890TR_YesNoMaybe activate = shouldActivateNewCompThread();4891if (activate == TR_maybe &&4892TR::Options::getCmdLineOptions()->getOption(TR_ActivateCompThreadWhenHighPriReqIsBlocked) &&4893getNumCompThreadsActive() == 1 &&4894priority >= CP_ASYNC_BELOW_MAX) // AOT loads and JNI4895{4896TR::CompilationInfoPerThread * lowPriCompThread = findFirstLowPriorityCompilationInProgress(priority);4897if (lowPriCompThread)4898{4899activate = TR_yes;49004901// Increase the weight of the blocking entry so that the newly activated thread4902// remains active until the blocking request gets compiled4903//4904TR_MethodToBeCompiled *lowPriCompReq = lowPriCompThread->getMethodBeingCompiled();4905uint8_t targetWeight = _compThreadSuspensionThresholds[2] <= 0xff ? _compThreadSuspensionThresholds[2] : 0xff;4906if (lowPriCompReq->_weight < targetWeight)4907{4908uint8_t diffWeight = targetWeight - lowPriCompReq->_weight;4909increaseQueueWeightBy(diffWeight);4910lowPriCompReq->_weight = targetWeight;4911}4912if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))4913TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u High priority req (0x%x) blocked by priority 0x%x",4914(uint32_t)getPersistentInfo()->getElapsedTime(), priority, lowPriCompReq->_priority);4915}4916}49174918if (activate == TR_yes)4919{4920// Must find one that is SUSPENDED/SUSPENDING otherwise the logic in shouldActivateNewCompThread is incorrect4921TR::CompilationInfoPerThread *compInfoPT = getFirstSuspendedCompilationThread();49224923TR_ASSERT_FATAL(compInfoPT != NULL, "Could not find a suspended/suspending compilation thread");49244925compInfoPT->resumeCompilationThread();4926if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))4927{4928TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Activate compThread %d Qweight=%d active=%d",4929(uint32_t)getPersistentInfo()->getElapsedTime(),4930compInfoPT->getCompThreadId(),4931getQueueWeight(),4932getNumCompThreadsActive());4933}4934}4935}49364937// Move the entry to the right place in the queue4938//4939queueEntry(cur);49404941return cur;4942}49434944//--------------------------- queueEntry ---------------------------------4945// Insert the compilation request in the queue at the appropriate place4946// based on its priority. Must have compilationQueueMonitor in hanb4947//------------------------------------------------------------------------4948void TR::CompilationInfo::queueEntry(TR_MethodToBeCompiled *entry)4949{4950TR_ASSERT_FATAL(entry->_freeTag & ENTRY_INITIALIZED, "queuing an entry which is not initialized\n");49514952entry->_freeTag |= ENTRY_QUEUED;49534954if (!_methodQueue || _methodQueue->_priority < entry->_priority)4955{4956entry->_next = _methodQueue;4957_methodQueue = entry;4958}4959else4960{4961for (TR_MethodToBeCompiled *prev = _methodQueue; ; prev = prev->_next)4962{4963if (!prev->_next || prev->_next->_priority < entry->_priority)4964{4965entry->_next = prev->_next;4966prev->_next = entry;4967break;4968}4969}4970}4971}49724973//--------------------------------- requeue ----------------------------------4974// Put the request that is currently being compiled, back into the queue4975// and increment the number of queued methods4976//----------------------------------------------------------------------------4977void TR::CompilationInfoPerThread::requeue()4978{4979TR_ASSERT(_methodBeingCompiled, "Invalid use of requeue.");4980_compInfo.incrementMethodQueueSize();4981if (_methodBeingCompiled->getMethodDetails().isOrdinaryMethod() && _methodBeingCompiled->_oldStartPC==0)4982_compInfo._numQueuedFirstTimeCompilations++;4983if (_methodBeingCompiled->_entryIsCountedAsInvRequest)4984_compInfo.incNumInvRequestsQueued(_methodBeingCompiled);4985_methodBeingCompiled->_compErrCode = compilationOK; // reset the error code4986_compInfo.queueEntry(_methodBeingCompiled);4987_methodBeingCompiled = NULL;4988}49894990//------------------------- adjustCompilationEntryAndRequeue -----------------4991// Search for the given method in the compilation queue4992// If found, we may adjust the optimization plan. There is a very good4993// likelihood that a matching entry will be found.4994//----------------------------------------------------------------------------4995TR_MethodToBeCompiled *4996TR::CompilationInfo::adjustCompilationEntryAndRequeue(4997TR::IlGeneratorMethodDetails &details,4998TR_PersistentMethodInfo *methodInfo,4999TR_Hotness newOptLevel, bool useProfiling,5000CompilationPriority priority,5001TR_J9VMBase *fe)5002{5003for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)5004{5005TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];5006TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");50075008if (curCompThreadInfoPT->getMethodBeingCompiled() &&5009curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().sameAs(details, fe))5010return NULL; // didn't do anything5011}50125013// Search the queue for my method5014TR_MethodToBeCompiled *cur, *prev;5015for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)5016{5017if (cur->getMethodDetails().sameAs(details, fe))5018break;5019}5020if (cur)5021{5022// here define the list of exclusions5023bool exclude = cur->getMethodDetails().isNewInstanceThunk() ||5024cur->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS; // do not do it for retrials5025// we could also do it only for upgrades cur->_optimizationPlan->isUpgradeRecompilation()5026if (exclude)5027{5028cur = NULL;5029}5030else5031{5032cur->_optimizationPlan->setOptLevel(newOptLevel);5033cur->_optimizationPlan->setInsertInstrumentation(useProfiling);5034methodInfo->setNextCompileLevel(newOptLevel, useProfiling);50355036if (cur->_priority < priority)5037{5038// take the method out5039if (prev)5040prev->_next = cur->_next;5041else5042_methodQueue = cur->_next;5043// put it back at its proper place5044cur->_priority = priority;5045queueEntry(cur);5046}5047}5048//fprintf(stderr, "Adjusting optimization plan in the queue\n");5049}5050return cur;5051}50525053int32_t TR::CompilationInfo::promoteMethodInAsyncQueue(J9Method * method, void *pc)5054{5055// See if the method is already in the queue or is already being compiled5056//5057for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)5058{5059TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];5060TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");50615062if (curCompThreadInfoPT->getMethodBeingCompiled() &&5063!curCompThreadInfoPT->getMethodBeingCompiled()->isDLTCompile() &&5064method == curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().getMethod())5065{5066changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 9);5067return 0; // didn't do anything5068}5069}50705071int i = 0;5072TR_MethodToBeCompiled *cur, *prev;5073for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)5074{5075if (!cur->isDLTCompile() && method == cur->getMethodDetails().getMethod())5076break;5077i++;5078}50795080if (!cur || !prev || cur->_priority >= CP_ASYNC_MAX || prev->_priority >= CP_ASYNC_MAX)5081return -i;5082changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 9);5083_statNumQueuePromotions++;5084#ifdef STATS5085fprintf(stderr, "Promoting method in queue QSZ=%d\n", getMethodQueueSize());5086#endif5087cur->_priority = CP_ASYNC_MAX;50885089// take the method out5090prev->_next = cur->_next;5091// find insertion point5092if (_methodQueue->_priority < CP_ASYNC_MAX) // common case5093{5094cur->_next = _methodQueue;5095_methodQueue = cur;5096// FIXME: how about the compilation lag5097}5098else5099{5100for (prev = _methodQueue; prev->_next; prev = prev->_next)5101if (prev->_next->_priority < CP_ASYNC_MAX)5102{5103cur->_next = prev->_next;5104prev->_next = cur;5105break;5106}5107}5108return i;5109}51105111void TR::CompilationInfo::changeCompReqFromAsyncToSync(J9Method * method)5112{51135114TR_MethodToBeCompiled *cur = NULL, *prev = NULL;5115// See if the method is already in the queue or is already being compiled5116//5117for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)5118{5119TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];5120TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");51215122if (curCompThreadInfoPT->getMethodBeingCompiled() &&5123!curCompThreadInfoPT->getMethodBeingCompiled()->isDLTCompile() &&5124method == curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().getMethod())5125{5126if (curCompThreadInfoPT->getMethodBeingCompiled()->_priority <= CP_ASYNC_MAX)5127{5128curCompThreadInfoPT->getMethodBeingCompiled()->_priority = CP_SYNC_NORMAL;5129cur = curCompThreadInfoPT->getMethodBeingCompiled();5130break;5131}5132}5133}5134if (!cur)5135{5136for (cur = _methodQueue; cur; prev = cur, cur = cur->_next)5137if (!cur->isDLTCompile() && method == cur->getMethodDetails().getMethod())5138break;5139// Check if this is an asynchronous request5140//5141if (cur && cur->_priority <= CP_ASYNC_MAX)5142{5143// Take the method out, increase its priority and insert it at the proper place5144//5145cur->_priority = CP_SYNC_NORMAL;5146if (prev)5147{5148prev->_next = cur->_next;5149queueEntry(cur);5150}5151else // method already at the top of the queue5152{5153// Nothing to do5154}5155}5156else5157{5158cur = NULL; // prevent further processing5159}5160}5161if (cur)5162{5163TR_ASSERT(!cur->_changedFromAsyncToSync, "_changedFromAsyncToSync must be false");5164J9Method *method = cur->getMethodDetails().getMethod();5165cur->_changedFromAsyncToSync = true; // Flag the method as synchronous5166// Allow new invocations to trigger compilations5167if (getJ9MethodVMExtra(method) == J9_JIT_QUEUED_FOR_COMPILATION)5168setInvocationCount(method, 0);5169// fprintf(stderr, "Changed method %p priority from async to sync\n", method);5170}5171}51725173// Must hold compilation queue monitor in hand5174// Should only be used when compiling on separate thread, otherwise5175// _arrayOfCompilationInfoPerThread does not exist (or is full of null pointers)5176TR_MethodToBeCompiled * TR::CompilationInfo::requestExistsInCompilationQueue(TR::IlGeneratorMethodDetails & details, TR_FrontEnd *fe)5177{5178// See if the method is already in the queue or under compilation5179//5180for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)5181{5182TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];5183TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");51845185if (5186curCompThreadInfoPT->getMethodBeingCompiled() &&5187curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().sameAs(details, fe) &&5188!curCompThreadInfoPT->getMethodBeingCompiled()->_unloadedMethod) // Redefinition; see cmvc 192606 and RTC 368985189return curCompThreadInfoPT->getMethodBeingCompiled();5190}51915192for (TR_MethodToBeCompiled *cur = _methodQueue; cur; cur = cur->_next)5193if (cur->getMethodDetails().sameAs(details, fe))5194return cur;5195return NULL;5196}51975198TR_MethodToBeCompiled *TR::CompilationInfo::peekNextMethodToBeCompiled()5199{5200if (_methodQueue)5201return _methodQueue;5202else if (getLowPriorityCompQueue().hasLowPriorityRequest() && canProcessLowPriorityRequest())5203// These upgrade requests should not hinder the application too much.5204// If possible, we should decrease the priority of the compilation thread5205// Note that on LINUX priorities do not work5206// If we cannot lower the priority, we should wait for some idle time5207// or space compilations apart. if we return NULL here, the compilation5208// thread will go to sleep and we need a mechanism to wake it up5209//5210return getLowPriorityCompQueue().getFirstLPQRequest();5211else if (!getJProfilingCompQueue().isEmpty() && canProcessJProfilingRequest())5212return getJProfilingCompQueue().getFirstCompRequest();5213else5214return NULL;5215}521652175218TR_MethodToBeCompiled *5219TR::CompilationInfo::getNextMethodToBeCompiled(TR::CompilationInfoPerThread *compInfoPT,5220bool compThreadCameOutOfSleep,5221TR_CompThreadActions *compThreadAction)5222{5223TR_MethodToBeCompiled *nextMethodToBeCompiled = NULL;52245225// Only the diagnostic thread should be processing JitDump compilations. This is to ensure proper tracing is active5226// and proper synchronization is performed w.r.t. special events (interpreter shutdown, etc.). The logic here is5227// split into two parts. In the event we are a diagnostic thread, the JitDump process will have ensured the method5228// compilation queue has been purged and all further compilations have been suspended until the entire JitDump5229// process in complete. This also means if we are a diagnostic thread, then the only entries in the queue should5230// be JitDump compile requests. We will ensure this is the case via a fatal assert.5231//5232// In addition there can be scenarios in which a non-diagnostic compilation thread is still attempting to process5233// entries while the JitDump process (in a crashed thread) is happening. This is because one compilation thread5234// must always be active, and there is a timing hole between purging of the queue in the JitDump process, and when5235// the diagnostic thread is resumed. This means a non-diagnostic thread could attempt to pick up a JitDump5236// compilation request (see eclipse-openj9/openj9#11772 for details). We must ensure that this does not happen and simply5237// skip the request if we are a non-diagnostic thread attempting to process a JitDump compilation.5238if (compInfoPT->isDiagnosticThread())5239{5240// We never want to self-suspend the diagnostic thread. The JitDump process will do it after it is complete.5241*compThreadAction = GO_TO_SLEEP_EMPTY_QUEUE;52425243if (_methodQueue)5244{5245nextMethodToBeCompiled = _methodQueue;5246_methodQueue = _methodQueue->_next;52475248// See explanation at the start of this function of why it is important to ensure this5249TR_ASSERT_FATAL(nextMethodToBeCompiled->getMethodDetails().isJitDumpMethod(), "Diagnostic thread attempting to process non-JitDump compilation");52505251*compThreadAction = PROCESS_ENTRY;5252}5253}5254else5255{5256*compThreadAction = PROCESS_ENTRY;52575258// Due to the above mentioned timing hole, a non-diagnostic compilation thread may still be trying to process5259// entries. We prevent it from processing JitDump compilation requests here.5260if (_methodQueue != NULL && !_methodQueue->getMethodDetails().isJitDumpMethod())5261{5262// If the request is sync or AOT load, take it now5263if (_methodQueue->_priority >= CP_SYNC_MIN // sync comp5264|| _methodQueue->_methodIsInSharedCache == TR_yes // very cheap relocation5265#if defined(J9VM_OPT_JITSERVER)5266|| getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER // compile right away in server mode5267#endif5268)5269{5270nextMethodToBeCompiled = _methodQueue;5271_methodQueue = _methodQueue->_next;5272}5273// Check if we need to throttle5274else if (exceedsCompCpuEntitlement() == TR_yes &&5275!compThreadCameOutOfSleep && // Don't throttle a comp thread that has just slept its share of time5276(TR::Options::_compThreadCPUEntitlement < 100 || getNumCompThreadsActive() * 100 > (TR::Options::_compThreadCPUEntitlement + 50)))5277{5278// If at all possible suspend the compilation thread5279// Otherwise, perform a timed wait5280if (getNumCompThreadsActive() > 1)5281*compThreadAction = SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;5282else5283*compThreadAction = THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;5284}5285// Avoid two concurrent hot compilations5286else if (getNumCompThreadsCompilingHotterMethods() <= 0 || // no hot compilation in progress5287_methodQueue->_weight < TR::Options::_expensiveCompWeight) // This is a cheaper comp5288{5289nextMethodToBeCompiled = _methodQueue;5290_methodQueue = _methodQueue->_next;5291}5292else // scan for a cold/warm method5293{5294TR_MethodToBeCompiled *prev = _methodQueue;5295for (nextMethodToBeCompiled = _methodQueue->_next; nextMethodToBeCompiled; prev = nextMethodToBeCompiled, nextMethodToBeCompiled = nextMethodToBeCompiled->_next)5296{5297if (nextMethodToBeCompiled->_optimizationPlan->getOptLevel() <= warm || // cheaper comp5298nextMethodToBeCompiled->_priority >= CP_SYNC_MIN || // sync comp5299nextMethodToBeCompiled->_methodIsInSharedCache == TR_yes) // very cheap relocation5300{5301prev->_next = nextMethodToBeCompiled->_next;5302break;5303}5304}5305if (!nextMethodToBeCompiled)5306{5307*compThreadAction = GO_TO_SLEEP_CONCURRENT_EXPENSIVE_REQUESTS;53085309// make sure there is at least one thread that is not jobless5310TR::CompilationInfoPerThread * const * arrayOfCompInfoPT = getArrayOfCompilationInfoPerThread();5311int32_t numActive = 0, numHot = 0, numLowPriority = 0;5312for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)5313{5314TR::CompilationInfoPerThread *curCompThreadInfoPT = arrayOfCompInfoPT[i];5315TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");53165317CompilationThreadState currentThreadState = curCompThreadInfoPT->getCompilationThreadState();5318if (5319currentThreadState == COMPTHREAD_ACTIVE5320|| currentThreadState == COMPTHREAD_SIGNAL_WAIT5321|| currentThreadState == COMPTHREAD_WAITING5322|| currentThreadState == COMPTHREAD_SIGNAL_SUSPEND5323)5324{5325if (curCompThreadInfoPT->getMethodBeingCompiled() &&5326curCompThreadInfoPT->getMethodBeingCompiled()->_priority < CP_ASYNC_NORMAL)5327numLowPriority++;5328if (curCompThreadInfoPT->compilationThreadIsActive())5329numActive++;5330if (curCompThreadInfoPT->getMethodBeingCompiled() &&5331curCompThreadInfoPT->getMethodBeingCompiled()->_hasIncrementedNumCompThreadsCompilingHotterMethods)5332numHot++;5333}5334}53355336// There is a method to be compiled, but this thread is not going to take it out of the queue5337// There are two cases when this might happen:5338// (1) Two hot requests going in parallel5339// (2) Two low priority requests going in parallel during startup phase5340TR_ASSERT(numHot >= 1 || numLowPriority >= 1, "We must have a comp thread working on a hot or low priority method %d %d", numHot, numLowPriority);53415342if (numActive <= 1) // Current thread is by default active because it tried to dequeue a request5343{5344// There is no thread left to handle the existing request5345// See defect 182392 for why this could have happened and for the solution5346//fprintf(stderr, "JIT WARNING: no active thread left to handle queued request\n");5347}5348// sanity checks5349if (getNumCompThreadsActive() != numActive)5350{5351TR_ASSERT(false, "Inconsistency with active threads %d %d\n", getNumCompThreadsActive(), numActive);5352setNumCompThreadsActive(numActive); // apply correction5353}5354if (getNumCompThreadsCompilingHotterMethods() != numHot)5355{5356TR_ASSERT(false, "Inconsistency with hot threads %d %d\n", getNumCompThreadsCompilingHotterMethods(), numHot);5357setNumCompThreadsCompilingHotterMethods(numHot); // apply correction5358}5359}5360}5361if (nextMethodToBeCompiled) // A request has been dequeued5362{5363updateCompQueueAccountingOnDequeue(nextMethodToBeCompiled);5364}5365}5366// When no request is in the main queue we can look in the low priority queue5367else if (getLowPriorityCompQueue().hasLowPriorityRequest() &&5368canProcessLowPriorityRequest())5369{5370// Check if we need to throttle5371if (exceedsCompCpuEntitlement() == TR_yes &&5372!compThreadCameOutOfSleep && // Don't throttle a comp thread that has just slept its share of time5373(TR::Options::_compThreadCPUEntitlement < 100 || getNumCompThreadsActive() * 100 > (TR::Options::_compThreadCPUEntitlement + 50))5374#if defined(J9VM_OPT_JITSERVER)5375&& !getLowPriorityCompQueue().getFirstLPQRequest()->shouldUpgradeOutOfProcessCompilation() // Don't throttle if compilation will be done remotely5376#endif5377)5378{5379// If at all possible suspend the compilation thread5380// Otherwise, perform a timed wait5381if (getNumCompThreadsActive() > 1)5382*compThreadAction = SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;5383else5384*compThreadAction = THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;5385}5386else5387{5388nextMethodToBeCompiled = getLowPriorityCompQueue().extractFirstLPQRequest();5389}5390}5391// Now let's look in the JProfiling queue5392else if (!getJProfilingCompQueue().isEmpty() && canProcessJProfilingRequest())5393{5394// Check if we need to throttle5395if (exceedsCompCpuEntitlement() == TR_yes &&5396!compThreadCameOutOfSleep && // Don't throttle a comp thread that has just slept its share of time5397(TR::Options::_compThreadCPUEntitlement < 100 || getNumCompThreadsActive() * 100 >(TR::Options::_compThreadCPUEntitlement + 50)))5398{5399// If at all possible suspend the compilation thread5400// Otherwise, perform a timed wait5401if (getNumCompThreadsActive() > 1)5402*compThreadAction = SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;5403else5404*compThreadAction = THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;5405}5406else5407{5408nextMethodToBeCompiled = getJProfilingCompQueue().extractFirstCompRequest();5409}5410}5411else5412{5413// Cannot take a request either from main queue or LPQ5414// If this is the last active compilation thread, then go to sleep,5415// otherwise suspend the compilation thread5416if (getNumCompThreadsActive() > 1)5417{5418*compThreadAction = SUSPEND_COMP_THREAD_EMPTY_QUEUE;5419}5420else5421{5422*compThreadAction = GO_TO_SLEEP_EMPTY_QUEUE;5423}5424}54255426if (nextMethodToBeCompiled != NULL)5427{5428// See explanation at the start of this function of why it is important to ensure this5429TR_ASSERT_FATAL(!nextMethodToBeCompiled->getMethodDetails().isJitDumpMethod(), "Non-diagnostic thread attempting to process JitDump compilation");5430}5431}54325433return nextMethodToBeCompiled;5434}54355436//----------------------------- computeCompThreadSleepTime ----------------------5437// Compute how much the compilation thread should sleep for throttling purposes5438// Parameters: compilationTimeMs is the wall clock time spent by previous5439// compilation5440// The return value is in ms.5441//-------------------------------------------------------------------------------5442int32_t TR::CompilationInfo::computeCompThreadSleepTime(int32_t compilationTimeMs)5443{5444int32_t sleepTimeMs = 1;5445if (TR::Options::_compThreadCPUEntitlement > 0)5446{5447sleepTimeMs = compilationTimeMs * (100 / TR::Options::_compThreadCPUEntitlement - 1);5448}5449// some bounds for sleep time5450if (sleepTimeMs < TR::Options::_minSleepTimeMsForCompThrottling) // too small values are not useful because of high overhead of calling wait()5451sleepTimeMs = TR::Options::_minSleepTimeMsForCompThrottling;5452if (sleepTimeMs > TR::Options::_maxSleepTimeMsForCompThrottling) // TODO: need an options for this value5453sleepTimeMs = TR::Options::_maxSleepTimeMsForCompThrottling;5454return sleepTimeMs;5455}54565457// FIXME: this should be called only when running async - i have not yet figured5458// out how to figure this info out for interpreted methods scheduled for their5459// first compilation5460bool TR::CompilationInfo::isQueuedForCompilation(J9Method * method, void *oldStartPC)5461{5462TR_ASSERT(oldStartPC, "isQueuedForCompilation should not be called for interpreted methods\n");54635464J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(oldStartPC);5465return linkageInfo->isBeingCompiled();5466}54675468#if defined(TR_HOST_X86)5469JIT_HELPER(initialInvokeExactThunkGlue);5470#else5471JIT_HELPER(_initialInvokeExactThunkGlue);5472#endif54735474void *TR::CompilationInfo::startPCIfAlreadyCompiled(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details, void *oldStartPC)5475{5476if (details.isNewInstanceThunk())5477{5478return jitNewInstanceMethodStartAddress(vmThread, static_cast<J9::NewInstanceThunkDetails &>(details).classNeedingThunk());5479}5480else if (details.isMethodHandleThunk())5481{5482J9::MethodHandleThunkDetails &thunkDetails = static_cast<J9::MethodHandleThunkDetails &>(details);5483if (!thunkDetails.isShareable())5484return NULL; // Don't let the presence of a shareable thunk interfere with other requests54855486J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;5487if (!jitConfig)5488return NULL;54895490void *thunkStartPC = NULL;5491TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, vmThread);54925493{5494TR::VMAccessCriticalSection startPCIfAlreadyCompiled(fe);5495uintptr_t methodHandle = *thunkDetails.getHandleRef();5496void *thunkAddress = fe->methodHandle_jitInvokeExactThunk(methodHandle);5497void *initialInvokeExactThunkGlueAddress;5498#if defined(J9ZOS390)5499initialInvokeExactThunkGlueAddress = (void*)TOC_UNWRAP_ADDRESS(_initialInvokeExactThunkGlue);5500#elif defined(TR_HOST_POWER) && (defined(TR_HOST_64BIT) || defined(AIXPPC)) && !defined(__LITTLE_ENDIAN__)5501initialInvokeExactThunkGlueAddress = (*(void **)_initialInvokeExactThunkGlue);5502#elif defined(TR_HOST_X86)5503initialInvokeExactThunkGlueAddress = (void*)initialInvokeExactThunkGlue;5504#else5505initialInvokeExactThunkGlueAddress = (void*)_initialInvokeExactThunkGlue;5506#endif5507if (thunkAddress != initialInvokeExactThunkGlueAddress)5508{5509// thunkAddress is the jit entry point for a thunk. We need to find5510// the corresponding startPC (which is the interpreter entry point).5511//5512// TODO:JSR292: This could also be a j2i thunk/helper address! Should5513// return NULL in that case. For now, set TR_DisableThunkTupleJ2I to5514// avoid this case.5515//5516J9JITHashTable *hashTable = (J9JITHashTable *) avl_search(jitConfig->translationArtifacts, (UDATA)thunkAddress);5517if (hashTable)5518{5519J9JITExceptionTable *metadata = hash_jit_artifact_search(hashTable, (UDATA)thunkAddress);5520if (metadata)5521thunkStartPC = (void*)metadata->startPC;5522}5523bool verboseDetails = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseMethodHandleDetails);5524if (verboseDetails)5525{5526if (thunkStartPC)5527TR_VerboseLog::writeLineLocked(TR_Vlog_MHD, "%p Metadata lookup: handle %p thunk body at %p has startPC %p", vmThread, (void*)methodHandle, thunkAddress, thunkStartPC);5528else5529TR_VerboseLog::writeLineLocked(TR_Vlog_MHD, "%p Metadata lookup FAILED for: handle %p thunk body at %p -- jit will probably create a redundant body", vmThread, (void*)methodHandle, thunkAddress);5530}5531}5532}55335534return thunkStartPC;5535}55365537void *startPC = 0;5538J9Method *method = details.getMethod();55395540if (!oldStartPC)5541{5542// first compilation of the method: J9Method would be updated if the5543// compilation has already taken place5544//5545startPC = getPCIfCompiled(method);5546}5547else5548{5549J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(oldStartPC);5550if (linkageInfo->recompilationAttempted())5551startPC = getPCIfCompiled(method);5552}5553return startPC;5554}55555556// Must have compilation monitor when calling this method5557void TR::CompilationInfo::recycleCompilationEntry(TR_MethodToBeCompiled *entry)5558{5559TR_ASSERT_FATAL((entry->_freeTag & (ENTRY_INITIALIZED)) || (entry->_freeTag & (ENTRY_IN_POOL_NOT_FREE|ENTRY_IN_POOL_FREE|ENTRY_DEALLOCATED)),5560"recycling an improper entry\n");5561entry->_freeTag |= ENTRY_IN_POOL_NOT_FREE;5562if (entry->_numThreadsWaiting == 0)5563entry->_freeTag |= ENTRY_IN_POOL_FREE;55645565entry->_next = _methodPool;5566_methodPool = entry;5567_methodPoolSize++;55685569// If the pool grows too big, start deallocating entries5570if (_methodPoolSize >= METHOD_POOL_SIZE_THRESHOLD)5571{5572TR_MethodToBeCompiled *prev = _methodPool;5573TR_MethodToBeCompiled *crt = _methodPool->_next;5574while (crt && _methodPoolSize >= METHOD_POOL_SIZE_THRESHOLD/2)5575{5576if (crt->_numThreadsWaiting == 0)5577{5578TR_ASSERT_FATAL(crt->_freeTag & ENTRY_IN_POOL_FREE, "Will deallocate an entry that is not free\n");55795580prev->_next = crt->_next;5581_methodPoolSize--;5582crt->shutdown(); // free the monitor and string associated with it5583PORT_ACCESS_FROM_JITCONFIG(_jitConfig);5584j9mem_free_memory(crt);5585crt = prev->_next;5586}5587else5588{5589prev = crt;5590crt = crt->_next;5591}5592}5593}5594}559555965597static void deleteMethodHandleRef(J9::MethodHandleThunkDetails & details, J9VMThread *vmThread, TR_FrontEnd *fe)5598{5599bool verboseDetails = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseMethodHandleDetails);5600TR_J9VMBase *fej9 = (TR_J9VMBase *)fe;56015602if (verboseDetails)5603{5604TR::VMAccessCriticalSection deleteMethodHandleRef(fej9);5605uintptr_t methodHandle = * details.getHandleRef();5606TR_VerboseLog::writeLineLocked(TR_Vlog_MHD,"%p Deleting MethodHandle %p global reference", vmThread, (j9object_t)methodHandle);5607}56085609vmThread->javaVM->internalVMFunctions->j9jni_deleteGlobalRef((JNIEnv*)vmThread, (jobject)details.getHandleRef(), false);5610if (details.getArgRef())5611vmThread->javaVM->internalVMFunctions->j9jni_deleteGlobalRef((JNIEnv*)vmThread, (jobject)details.getArgRef(), false);5612}561356145615void *TR::CompilationInfo::compileMethod(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details, void *oldStartPC,5616TR_YesNoMaybe requireAsyncCompile,5617TR_CompilationErrorCode *compErrCode,5618bool *queued, TR_OptimizationPlan * optimizationPlan)5619{5620TR_J9VMBase * fe = TR_J9VMBase::get(_jitConfig, vmThread);5621TR_ASSERT(!fe->isAOT_DEPRECATED_DO_NOT_USE(), "We need a non-AOT vm here.");56225623J9Method *method = details.getMethod();56245625J9::NewInstanceThunkDetails * newInstanceThunkDetails = NULL;5626if (details.isNewInstanceThunk())5627newInstanceThunkDetails = & static_cast<J9::NewInstanceThunkDetails &>(details);56285629J9::MethodHandleThunkDetails *methodHandleThunkDetails = NULL;5630if (details.isMethodHandleThunk())5631methodHandleThunkDetails = & static_cast<J9::MethodHandleThunkDetails &>(details);56325633J9Class *clazz = details.getClass();56345635bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest);5636if (verbose)5637{5638TR_VerboseLog::CriticalSection vlogLock;5639TR_VerboseLog::write(TR_Vlog_CR, "%p Compile request %s", vmThread, details.name());56405641if (newInstanceThunkDetails)5642{5643if (clazz)5644{5645int32_t len;5646char * className = fe->getClassNameChars(fe->convertClassPtrToClassOffset(clazz), len);5647TR_VerboseLog::write(" j9class=%p %.*s", clazz, len, className);5648}5649}5650else if (methodHandleThunkDetails)5651{5652// No vm access needed here, because we're not inspecting the handle object -- only printing its address.5653TR_VerboseLog::write(" handle=%p", (void*)*(methodHandleThunkDetails->getHandleRef()));5654if (methodHandleThunkDetails->getArgRef())5655TR_VerboseLog::write(" arg=%p", (void*)*(methodHandleThunkDetails->getArgRef()));5656}56575658char buf[500];5659fe->printTruncatedSignature(buf, sizeof(buf), (TR_OpaqueMethodBlock *)method);5660TR_VerboseLog::write(" j9method=%p %s optLevel=%d", method, buf, optimizationPlan->getOptLevel());5661if (clazz && J9_IS_CLASS_OBSOLETE(clazz))5662{5663TR_ASSERT(!fe->isAOT_DEPRECATED_DO_NOT_USE(), "Shouldn't get obsolete classes in AOT");5664TR_VerboseLog::write(" OBSOLETE class=%p -- request declined", clazz);5665}5666TR_VerboseLog::writeLine("");5667}56685669// Pin the class of the method in case GC wants to unload it5670bool classPushed = false;5671// Why wouldn't we do this for AOT??5672if (!fe->isAOT_DEPRECATED_DO_NOT_USE())5673{5674if (clazz && J9_IS_CLASS_OBSOLETE(clazz))5675return NULL;56765677PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(clazz));5678classPushed = true;5679}56805681#ifdef J9VM_JIT_GC_ON_RESOLVE_SUPPORT5682// If gcOnResolve, scavenge now, unless the JIT is in test mode,5683// and not connected to a real fe. Do this only when recompiling5684// or when compiling a newInstanceThunk (otherwise we're too slow)5685//5686if ( (_jitConfig->runtimeFlags & J9JIT_SCAVENGE_ON_RESOLVE) &&5687!(_jitConfig->runtimeFlags & J9JIT_TOSS_CODE) && !requireAsyncCompile &&5688(oldStartPC || newInstanceThunkDetails))5689jitCheckScavengeOnResolve(vmThread);5690#endif56915692void *startPC = 0;5693bool needCompile = true;56945695// always need to compile if it's a log compilation5696if (!(optimizationPlan->isLogCompilation()))5697{5698if (newInstanceThunkDetails)5699{5700// Ask the VM if this compilation is required5701//5702startPC = jitNewInstanceMethodStartAddress(vmThread, clazz);5703if (startPC || fe->isAOT_DEPRECATED_DO_NOT_USE())5704needCompile = false;5705} // if5706else if (!oldStartPC && !details.isMethodInProgress())5707{5708startPC = getPCIfCompiled(method);5709if (startPC)5710{5711debugPrint("\tcompile request already done", method); //, vmThread, entry->getMethodDetails());5712needCompile = false;5713}5714} // if5715else if (oldStartPC) // recompilation case5716{5717if (fe->isAOT_DEPRECATED_DO_NOT_USE())5718{5719J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(oldStartPC);5720if (linkageInfo->recompilationAttempted())5721{5722startPC = getPCIfCompiled(method); // provide the new startPC5723// must look like a compiled method5724if (startPC)5725{5726debugPrint("\tcompile request already done", method); //, vmThread, entry->getMethodDetails());5727needCompile = false;5728}5729} // if5730} // if5731} // if5732} // if !isLogCompilation()57335734if (optimizationPlan->isGPUCompilation())5735needCompile=1;57365737if (needCompile)5738{5739// AOT goes to application thread?5740if (!fe->isAOT_DEPRECATED_DO_NOT_USE())5741startPC = compileOnSeparateThread(vmThread, details, oldStartPC, requireAsyncCompile, compErrCode, queued, optimizationPlan);5742}5743else5744{5745if (compErrCode)5746*compErrCode = compilationNotNeeded;5747}57485749if (!fe->isAOT_DEPRECATED_DO_NOT_USE())5750if (classPushed)5751POP_OBJECT_IN_SPECIAL_FRAME(vmThread);5752return startPC;5753}57545755#if defined(J9VM_OPT_SHARED_CLASSES)5756extern bool5757validateSharedClassAOTHeader(J9JavaVM *javaVM, J9VMThread *curThread, TR::CompilationInfo *compInfo, TR_FrontEnd *fe);5758#endif57595760void *TR::CompilationInfo::compileOnSeparateThread(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details,5761void *oldStartPC, TR_YesNoMaybe requireAsyncCompile,5762TR_CompilationErrorCode *compErrCode,5763bool *queued,5764TR_OptimizationPlan * optimizationPlan)5765{5766void *startPC = NULL;57675768J9Method *method = details.getMethod();5769TR_J9VMBase *fe = TR_J9VMBase::get(_jitConfig, vmThread);57705771// Grab the compilation monitor5772//5773debugPrint(vmThread, "\tapplication thread acquiring compilation monitor\n");5774acquireCompMonitor(vmThread);5775debugPrint(vmThread, "+CM\n");57765777// Even before checking whether compilation threads are active, we need5778// to check if a compilation for this body has already been performed57795780// Now that we have the lock5781// Check if the compilation is already done by looking at the J9Method/LinkageInfo.5782//5783// If it is not already done, then either5784// 1 - we are the first thread to get here, we will create a brand new entry in the queue.5785// 2 - an entry in the queue already exists - a compilation is in progress or in queue5786// that hasn't finished yet. We will definitely find the old entry when we try to add5787// to the queue.5788//5789if (!details.isMethodInProgress())5790startPC = startPCIfAlreadyCompiled(vmThread, details, oldStartPC);5791if (startPC && !details.isJitDumpMethod() &&5792!optimizationPlan->isGPUCompilation())5793{5794// Release the compilation lock and return5795debugPrint(vmThread, "\tapplication thread releasing compilation monitor - compile already done\n");5796debugPrint(vmThread, "-CM\n");5797releaseCompMonitor(vmThread);5798if (compErrCode)5799*compErrCode = compilationNotNeeded;5800if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))5801TR_VerboseLog::writeLineLocked(TR_Vlog_CR,"%p Already compiled at %p", startPC);5802return startPC;5803}58045805// If there are no active threads ready to perform the compilation or further compilations are disabled we will5806// end this compilation request. The only exception to this case is if we are performing a JitDump compilation,5807// in which case we always want to proceed with the compilation since it will be performed on the diagnostic5808// thread. Note that the diagnostic thread is not counted towards `getNumCompThreadsActive` count.5809if ((getNumCompThreadsActive() == 0 || getPersistentInfo()->getDisableFurtherCompilation()) && !details.isJitDumpMethod())5810{5811bool shouldReturn = true;58125813// Fail the compilation, unless this is on the queue (maybe even in progress)5814if (!requestExistsInCompilationQueue(details, fe))5815{5816startPC = compilationEnd(vmThread, details, _jitConfig, 0, oldStartPC);5817}5818else // Similar request already exists in the queue. We cannot fail this compilation5819{5820// If this is a sync compilation we must wait for the queued compilation to finish5821// Otherwise, code patching could put as in an infinite loop (see 185740)5822// It's also safe to continue for async compilations: if a similar request5823// already exists we will bail out and let the Java thread go.5824shouldReturn = false;5825if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompFailure, TR_VerboseCompileRequest))5826{5827TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"t=%u <WARNING: JIT Compilations are suspended. Current request will be coalesced with existing one in the queue>", (uint32_t)getPersistentInfo()->getElapsedTime());5828}5829}58305831if (shouldReturn)5832{5833debugPrint(vmThread, "\tapplication thread release compilation monitor - comp thread AWOL\n");5834debugPrint(vmThread, "-CM\n");5835releaseCompMonitor(vmThread);5836if (compErrCode)5837*compErrCode = compilationSuspended;58385839// Update statistics regarding the reason for compilation failure5840updateCompilationErrorStats(compilationSuspended);58415842if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompFailure, TR_VerboseCompileRequest))5843{5844TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"t=%u <WARNING: JIT Compilations are suspended>", (uint32_t)getPersistentInfo()->getElapsedTime());5845}58465847return startPC;5848}5849}585058515852// Determine if the compilation is going to be synchronous or asynchronous.5853// newInstance Thunks, and invalidated methods need be compiled synchronously5854//5855debugPrint(vmThread, "\tQueuing ");58565857TR_ASSERT(asynchronousCompilation() || requireAsyncCompile != TR_yes, "We cannot require async compilation when it is turned off");58585859bool forcedSync = false;5860bool async = asynchronousCompilation() && requireAsyncCompile != TR_no;5861if (async)5862{5863J9::PrivateLinkage::LinkageInfo *linkageInfo = oldStartPC ? J9::PrivateLinkage::LinkageInfo::get(oldStartPC) : 0;5864if (requireAsyncCompile != TR_yes && !oldStartPC && !details.isMethodInProgress())5865{5866J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);5867// if the method is specified to be compiled at count=0, -Xjit:{*method*}(count=0), then do it synchronously5868//5869if (TR::Options::getJITCmdLineOptions()->anOptionSetContainsACountValue() ||5870TR::Options::getAOTCmdLineOptions()->anOptionSetContainsACountValue())5871{5872bool hasBackwardBranches = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod)) ? true : false;5873bool isAOT = !TR::Options::getJITCmdLineOptions()->anOptionSetContainsACountValue();5874TR::OptionSet * optionSet = findOptionSet(method, isAOT);58755876if (optionSet &&5877(optionSet->getOptions()->getInitialCount() == 0 ||5878(optionSet->getOptions()->getInitialBCount() == 0 && hasBackwardBranches)))5879async = false;5880}58815882if (async)5883{5884bool isORB = false;5885J9ROMClass *declaringClazz = J9_CLASS_FROM_METHOD(method)->romClass;5886J9UTF8 * className = J9ROMCLASS_CLASSNAME(declaringClazz);5887if (J9UTF8_LENGTH(className) == 36 &&58880==memcmp(utf8Data(className), "com/ibm/rmi/io/FastPathForCollocated", 36))5889{5890J9UTF8 *utf8 = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(method));5891if (J9UTF8_LENGTH(utf8)==21 &&58920==memcmp(J9UTF8_DATA(utf8), "isVMDeepCopySupported", 21))5893isORB = true;5894}58955896if (fe && requireAsyncCompile != TR_yes && isORB)5897async = false;5898}5899}59005901if (!async)5902{5903debugPrint("forced synchronous");5904forcedSync = true;5905}5906else5907{5908debugPrint("asynchronous");5909// for async requests we can avoid checking the queue5910if ((linkageInfo && linkageInfo->isBeingCompiled()) || // for jitted methods5911(oldStartPC == 0 && // for interpreted methods5912details.isOrdinaryMethod() &&5913getJ9MethodVMExtra(details.getMethod()) == J9_JIT_QUEUED_FOR_COMPILATION)) // this will also filter out JNI natives5914{5915// Release the compilation lock and return5916debugPrint(vmThread, "\tapplication thread releasing compilation monitor - comp.req. in progress\n");5917debugPrint(vmThread, "-CM\n");5918releaseCompMonitor(vmThread);5919if (compErrCode)5920*compErrCode = compilationInProgress;5921return 0; // mark that compilation is not yet done5922}5923// When the compilation queue is very large, it may be better to postpone5924// the asynchronous compilations by replenishing the invocation counter.5925// This avoids the overhead associated with searching the right place to5926// insert into the compilation queue (which is a priority queue)5927if (getMethodQueueSize() >= TR::Options::_qszLimit &&5928oldStartPC == 0 && // Only look at interpreted methods5929details.isOrdinaryMethod()) // Do not apply this optimization to DLT5930{5931J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);5932if (!(romMethod->modifiers & J9AccNative)) // We are not allowed to change the invocation count for native methods5933{5934int32_t newCount = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;5935bool success = TR::CompilationInfo::replenishInvocationCountIfExpired(method, newCount);5936if (success)5937{5938if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))5939{5940TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Reencoding count=%d for j9m=%p because Q_SZ is too large", newCount, method);5941}5942// Release the compilation lock and return5943debugPrint(vmThread, "\tapplication thread releasing compilation monitor - comp.req. in progress\n");5944debugPrint(vmThread, "-CM\n");5945releaseCompMonitor(vmThread);5946if (compErrCode)5947*compErrCode = compilationNotNeeded;5948return 0; // mark that compilation is not yet done5949}5950}5951}5952}5953}5954else5955{5956debugPrint("synchronous");5957}59585959#if defined(J9VM_OPT_METHOD_HANDLE)5960// Check to make sure we never queue a thunk archetype5961// See JTC-JAT 563145962if (details.isOrdinaryMethod() || details.isMethodInProgress())5963{5964J9Method *method = (J9Method*)details.getMethod();5965J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);59665967if (_J9ROMMETHOD_J9MODIFIER_IS_SET(romMethod, J9AccMethodFrameIteratorSkip))5968{5969if (details.isMethodHandleThunk())5970{5971if (compErrCode)5972*compErrCode = compilationFailure;59735974debugPrint(vmThread, "\tapplication thread releasing compilation monitor - trying to compile thunk archetype\n");5975debugPrint(vmThread, "-CM\n");5976releaseCompMonitor(vmThread);5977return 0; // In prod, it's safe just to fail to queue the method5978}5979else5980{5981TR_ASSERT(0, "Should never attempt a JavaOrdinaryMethod compilation on a method with the J9AccMethodFrameIteratorSkip flag");5982Assert_JIT_unreachable();5983}5984}5985}5986#endif /* defined(J9VM_OPT_METHOD_HANDLE) */59875988TR_YesNoMaybe methodIsInSharedCache = TR_no;5989bool useCodeFromSharedCache = false;5990#if defined(J9VM_INTERP_AOT_RUNTIME_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))5991// Check to see if we find the method in the shared cache5992// If yes, raise the priority to be processed ahead of other methods5993//59945995if (TR::Options::sharedClassCache() && !TR::Options::getAOTCmdLineOptions()->getOption(TR_NoLoadAOT) && details.isOrdinaryMethod())5996{5997if (!isJNINative(method) && !isCompiled(method))5998{5999// If the method is in shared cache but we decide not to take it from there6000// we must bump the count, because this is a method whose count was decreased to scount6001// We can get the answer wrong if the method was not in the cache to start with, but other6002// other JVM added the method to the cache meanwhile. The net effect is that the said6003// method may have its count bumped up and compiled later6004//6005if (vmThread->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, fe->getROMMethodFromRAMMethod(method)))6006{6007if (static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_yes)6008{6009methodIsInSharedCache = TR_yes;6010useCodeFromSharedCache = true;6011}6012else6013{6014TR_ASSERT_FATAL(static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader != TR_maybe, "Should not be possible for aotValidHeader to be TR_maybe at this point\n");6015}6016}6017}6018}6019#endif // defined(J9VM_INTERP_AOT_RUNTIME_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))60206021// determine priority6022CompilationPriority compPriority = CP_SYNC_NORMAL;6023if (async)6024{6025if (details.isMethodInProgress())6026compPriority = CP_ASYNC_BELOW_MAX;6027else if (details.isMethodHandleThunk())6028{6029if (static_cast<J9::MethodHandleThunkDetails &>(details).isShareable())6030{6031// Shareable thunks are quick to compile and provide much benefit over interpreter6032//6033compPriority = CP_ASYNC_ABOVE_NORMAL;6034}6035else if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableReducedPriorityForCustomMethodHandleThunks))6036{6037// Custom thunks are expensive to compile and likely provide less benefit6038// than compiling the java code that calls (and hopefully inlines) them.6039//6040compPriority = CP_ASYNC_BELOW_NORMAL;6041}6042}6043else6044{6045compPriority = CP_ASYNC_NORMAL;6046if (oldStartPC) // compiled method6047{6048TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(oldStartPC);6049TR_ASSERT(bodyInfo, "assertion failure: bodyInfo is NULL");60506051TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();6052TR_ASSERT(methodInfo, "assertion failure: methodInfo is NULL");60536054TR_Hotness hotness = bodyInfo->getHotness();60556056TR_Hotness nextHotness = optimizationPlan->getOptLevel();605760586059// Recompilations of profiling bodies are problematic when a large number of6060// threads is used and the compilation thread is starved; once we decided we6061// are done with the profiling step we must compile the next body sooner rather6062// than later6063if (bodyInfo->getIsProfilingBody() && !TR::Options::getCmdLineOptions()->getOption(TR_DisablePostProfileCompPriorityBoost))6064{6065if (getMethodQueueSize() > TR::Options::_compPriorityQSZThreshold)6066compPriority = CP_ASYNC_ABOVE_NORMAL;6067}6068// decrease priority of upgrades6069// Also decrease priority of any recompilations during classLoadPhase6070// Also decrease priority of GCR recompilations6071// Also decrease priority of RI recompilations6072else if (optimizationPlan->isUpgradeRecompilation() ||6073getPersistentInfo()->isClassLoadingPhase() ||6074(bodyInfo->getUsesGCR() && nextHotness < hot) ||6075(methodInfo->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToRI))6076compPriority = CP_ASYNC_BELOW_NORMAL;6077// give priority to very-hot, scorching requests6078else if (nextHotness > hot && (dynamicThreadPriority() || compBudgetSupport()))6079compPriority = CP_ASYNC_ABOVE_NORMAL;6080// hot methods below 6% will be given lower priority6081else if (nextHotness == hot &&6082optimizationPlan->getPerceivedCPUUtil() <= (TR::Options::_sampleInterval * 1000 / TR::Options::_veryHotSampleThreshold) &&6083bodyInfo->getSamplingRecomp()) // recompilation triggered through sampling (as opposed to EDO)6084{6085compPriority = CP_ASYNC_BELOW_NORMAL;6086//fprintf(stderr, "CP_ASYNC_BELOW_NORMAL\n");6087}6088}6089else // interpreted method6090{6091// increase priority of JNI thunks6092if (method && isJNINative(method))6093compPriority = CP_ASYNC_ABOVE_NORMAL;6094#if defined(J9VM_INTERP_AOT_RUNTIME_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))6095else if (useCodeFromSharedCache) // Use higher priority for methods from shared cache6096compPriority = CP_ASYNC_BELOW_MAX;6097#endif6098}6099}6100if (TR::Options::getCmdLineOptions()->getOption(TR_EnableEarlyCompilationDuringIdleCpu) &&6101oldStartPC == 0 && // interpreted method6102compPriority <= CP_ASYNC_NORMAL &&6103details.isOrdinaryMethod() && // exclude DLT and thunks6104!useCodeFromSharedCache && // exclude AOT loads6105!isJNINative(method) // exclude JNI6106)6107{6108// Search the LPQ and if not found, add method to LPQ and bump invocation count6109// If method found, it means counter expired a second time, so move request to main queue6110TR_CompilationErrorCode err = scheduleLPQAndBumpCount(details, fe);6111if (err != compilationOK)6112{6113// Release the compilation lock before returning6114debugPrint(vmThread, "\tapplication thread releasing compilation monitor - comp.req. in progress\n");6115debugPrint(vmThread, "-CM\n");6116releaseCompMonitor(vmThread);6117if (compErrCode)6118*compErrCode = err;6119return 0; // mark that compilation is not yet done6120}6121}6122}// if (async)612361246125// Set up the compilation request6126//6127debugPrint(" compile request", method);612861296130TR_MethodToBeCompiled *entry =6131addMethodToBeCompiled(details, oldStartPC, compPriority, async,6132optimizationPlan, queued, methodIsInSharedCache);61336134if (entry == NULL)6135{6136releaseCompMonitor(vmThread);6137if (compErrCode)6138*compErrCode = compilationFailure;6139return 0; // We couldn't add a method entry to be compiled.6140}61416142#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)6143if (details.isMethodInProgress() &&6144!isCompiled(method) &&6145*queued &&6146!TR::Options::getCmdLineOptions()->getOption(TR_DisableDLTrecompilationPrevention))6147{6148// Scan the queue for a J9 request of the same j9method and make this request synchronous6149// The DLT flag means that we cannot have JNI or newInstance6150if (!async)6151changeCompReqFromAsyncToSync(method);6152else6153{6154TR_MethodToBeCompiled *reqMe, *prevReq;6155for (prevReq=NULL, reqMe=_methodQueue; reqMe; prevReq = reqMe, reqMe = reqMe->_next)6156{6157if (!reqMe->isDLTCompile() && reqMe->getMethodDetails().getMethod() == method)6158break;6159}6160if (reqMe && reqMe->_priority<CP_ASYNC_ABOVE_NORMAL)6161{6162reqMe->_priority = CP_ASYNC_ABOVE_NORMAL;6163if (prevReq && prevReq->_priority<CP_ASYNC_ABOVE_NORMAL)6164{6165prevReq->_next = reqMe->_next;6166queueEntry(reqMe);6167}6168}6169}6170}6171#endif // J9VM_JIT_DYNAMIC_LOOP_TRANSFER61726173// If a request is already queued for this method, see if we need to block6174// waiting for the compilation result. Do not wait if the requester specifically asks6175// for an asynchronous compilation (very rare event possible due to some races)6176//6177if (!(*queued) && entry->_changedFromAsyncToSync && requireAsyncCompile != TR_yes)6178{6179async = false;6180forcedSync = true;6181}6182entry->_async = async;61836184// no need to grab slot monitor or releasing VM access if we are doing async6185if (async)6186{6187printQueue();61886189// The compilation thread may be running at very low priority6190// Speed it up6191/*6192if (dynamicThreadPriority())6193{6194if (compPriority >= CP_ASYNC_ABOVE_NORMAL)6195{6196changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 10);6197}6198else if (getMethodQueueSize() >= LARGE_QUEUE)6199{6200changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 13);6201}6202else if (getCompThreadPriority() < J9THREAD_PRIORITY_NORMAL)6203{6204changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 14);6205}6206}6207*/6208#ifdef STATS6209//if (compPriority >= CP_ASYNC_ABOVE_NORMAL)6210// fprintf(stderr, "Adding request at priority CP_ASYNC_ABOVE_NORMAL\n");6211#endif62126213// We can avoid notifying the compilation thread if there were6214// other requests in the compilation queue6215// However we have to consider the case when one of the comp threads (though active)6216// is waiting on comp monitor because it wants the avoid two hot concurrent compilations6217// (if the really active comp thread gets suspended we remain with just one comp thread6218// sleeping and no notification will be sent)6219if (getMethodQueueSize() <= 1 ||6220getNumCompThreadsJobless() > 0) // send notification if any thread is sleeping on comp monitor waiting for suitable work6221{6222debugPrint(vmThread, "\tnotifying the compilation thread of the compile request\n");6223getCompilationMonitor()->notifyAll();6224debugPrint(vmThread, "ntfy-CM\n");6225}6226// TODO find a way to wake up only one compilation thread62276228// Release the compilation monitor6229//6230debugPrint(vmThread, "\tapplication thread releasing compilation monitor\n");6231debugPrint(vmThread, "-CM\n");6232releaseCompMonitor(vmThread);62336234if (compErrCode)6235*compErrCode = compilationInProgress;62366237startPC = 0; // return 0 to show the compilation hasn't already been done6238}6239else // synchronous request6240{6241TR_ASSERT(requireAsyncCompile != TR_yes, "An async compile request is being forced to go in sync");62426243// Grab the application thread monitor6244//6245debugPrint(vmThread, "\tapplication thread acquiring monitor for queue slot\n");6246entry->acquireSlotMonitor(vmThread);6247debugPrint(vmThread, "+AM-", entry);62486249printQueue();6250// synchronous requests must receive immediate attention6251if (dynamicThreadPriority())6252changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 11);6253debugPrint(vmThread, "\tnotifying the compilation thread of the compile request\n");6254getCompilationMonitor()->notifyAll();6255debugPrint(vmThread, "ntfy-CM\n");62566257// Temporary sanity check6258TR_ASSERT_FATAL(entry->_numThreadsWaiting != 0x7fff, "ERROR _numThreadsWaiting is about to overflow\n");62596260// Before releasing the compilation monitor, mark that we have one more thead waiting for this entry6261//6262entry->_numThreadsWaiting++;62636264// Release the compilation monitor6265//6266debugPrint(vmThread, "\tapplication thread releasing compilation monitor\n");6267debugPrint(vmThread, "-CM\n");6268releaseCompMonitor(vmThread);62696270// Release VM Access6271//6272debugPrint(vmThread, "\tapplication thread releasing VM access\n");6273releaseVMAccess(vmThread);6274debugPrint(vmThread, "-VMacc\n");62756276// wait for compilation to finish.6277//6278debugPrint(vmThread, "\tapplication thread waiting for compile to finish\n");6279debugPrint(vmThread, "wait-", entry);6280entry->getMonitor()->wait();62816282debugPrint(vmThread, "\tapplication thread re-acquired queue slot monitor (got notification of compilation)\n");6283debugPrint(vmThread, "+AM-", entry);62846285// Now the compilation should have been done (or the compilation6286// thread has been stopped or suspended).6287//6288startPC = entry->_newStartPC;6289// For HCR should we return 0 or oldStartPC?6290if (startPC && startPC != oldStartPC)6291debugPrint("\tcompile request succeeded", entry->getMethodDetails(), vmThread);6292else6293debugPrint("\tcompile request failed", entry->getMethodDetails(), vmThread);6294if (compErrCode)6295*compErrCode = (TR_CompilationErrorCode)entry->_compErrCode;62966297//freeMethodToBeCompiled(entry);62986299// Release the monitor now6300//6301debugPrint(vmThread, "\tapplication thread releasing AppMonitor\n");6302debugPrint(vmThread, "-AM-", entry);63036304entry->releaseSlotMonitor(vmThread);63056306// Grab the compilation mutex to be able to decrement numThreadsWaiting6307// and access entryShouldBeDeallocated6308// When numThreadsWaiting reaches 0, the entry can be reused or deallocated6309//6310acquireCompMonitor(vmThread);63116312#if defined(J9VM_OPT_JITSERVER)6313// If a remote sync compilation has been changed to a local sync compilation,6314// queue a new remote async compilation entry for this method.6315// - The second compilation is queued only when this is the last thread waiting6316// for the compilation of the method.6317// - If for any reason, the current compilation request is changed to a sync6318// compilation from an async compilation, it probably means we can’t do an6319// async compilation. Don't queue the second async remote compilation.6320if (entry->hasChangedToLocalSyncComp() &&6321(entry->_numThreadsWaiting <= 1) &&6322!forcedSync &&6323(startPC && startPC != oldStartPC))6324{6325void *currOldStartPC = startPCIfAlreadyCompiled(vmThread, details, startPC);6326// If currOldStartPC is NULL, the method body defined by startPC has not been6327// recompiled. We will queue the second remote aync compilation here. Otherwise,6328// another thread is doing the recompilation and will take care of queueing6329// the second compilation.6330if (!currOldStartPC)6331{6332CompilationPriority compPriority = CP_ASYNC_NORMAL;6333bool queuedForRemote = false;6334bool isAsync = true;6335TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(entry->_origOptLevel);6336TR_YesNoMaybe mthInSharedCache = TR_no;63376338if (plan)6339{6340TR_MethodToBeCompiled *entryRemoteCompReq = addMethodToBeCompiled(details, currOldStartPC, compPriority, isAsync,6341plan, &queuedForRemote, mthInSharedCache);63426343if (entryRemoteCompReq)6344{6345entryRemoteCompReq->_async = isAsync;63466347if (getMethodQueueSize() <= 1 ||6348getNumCompThreadsJobless() > 0) // send notification if any thread is sleeping on comp monitor waiting for suitable work6349{6350getCompilationMonitor()->notifyAll();6351}6352if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))6353TR_VerboseLog::writeLineLocked(TR_Vlog_CR,"%p Queued a remote async compilation: entry=%p, j9method=%p",6354vmThread, entryRemoteCompReq, entryRemoteCompReq->getMethodDetails().getMethod());6355}6356if (!queuedForRemote)6357TR_OptimizationPlan::freeOptimizationPlan(plan);6358}6359}6360}6361#endif /* defined(J9VM_OPT_JITSERVER) */63626363entry->_numThreadsWaiting--;63646365TR_ASSERT_FATAL(!(entry->_freeTag & (ENTRY_DEALLOCATED|ENTRY_IN_POOL_FREE)), "Java thread waking up with a freed entry");63666367if (entry->_numThreadsWaiting == 0) // The tag should be ENTRY_IN_POOL_NOT_FREE6368if (entry->_freeTag & ENTRY_IN_POOL_NOT_FREE) // comp thread has recycled this entry6369entry->_freeTag |= ENTRY_IN_POOL_FREE;6370//else Do nothing cause we'll wait for the comp thread to completely recycle the entry63716372// Temporary sanity check because PPC does not use prod with assumes.6373TR_ASSERT_FATAL(entry->_numThreadsWaiting >= 0, "ERROR _numThreadsWaiting has become negative");63746375if (entry->_entryShouldBeDeallocated && entry->_numThreadsWaiting == 0)6376{6377entry->shutdown();6378PORT_ACCESS_FROM_JITCONFIG(_jitConfig);6379j9mem_free_memory(entry);6380}6381releaseCompMonitor(vmThread);63826383// Reacquire VM access6384//6385acquireVMAccess(vmThread);6386debugPrint(vmThread, "+VMacc\n");6387} // synchronous requests63886389return startPC;6390}63916392#ifdef TR_HOST_S3906393void6394TR::CompilationInfoPerThreadBase::outputVerboseMMapEntry(6395TR_ResolvedMethod *compilee,6396const struct tm &date,6397const struct timeval &time,6398void *startPC,6399void *endPC,6400const char *fmt,6401const char *profiledString,6402const char *compileString6403)6404{6405TR_VerboseLog::writeLine(6406TR_Vlog_MMAP,6407fmt,6408date.tm_hour,6409date.tm_min,6410date.tm_sec,6411time.tv_usec,6412compilee->classNameLength(), compilee->classNameChars(),6413compilee->nameLength(), compilee->nameChars(),6414compilee->signatureLength(), compilee->signatureChars(),6415"[",6416profiledString,6417compileString,6418"]",6419startPC,6420endPC6421);6422}64236424void6425TR::CompilationInfoPerThreadBase::outputVerboseMMapEntries(6426TR_ResolvedMethod *compilee,6427TR_MethodMetaData *metaData,6428const char *profiledString,6429const char *compileString6430)6431{64326433#if defined(TR_HOST_64BIT) || defined(TR_TARGET_64BIT)6434static const char *fmtNoEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%016p,%016p";6435static const char * fmtEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%016p,%016p\n";6436#else6437static const char *fmtNoEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%x,%x";6438static const char * fmtEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%x,%x\n";6439#endif6440struct timeval time;6441gettimeofday(&time, 0);6442struct tm date;6443if (!localtime_r(&time.tv_sec, &date)) return;64446445TR_VerboseLog::CriticalSection vlogLock;6446outputVerboseMMapEntry(6447compilee,6448date,6449time,6450reinterpret_cast<void *>(metaData->startPC),6451reinterpret_cast<void *>(metaData->endWarmPC),6452fmtNoEOL,6453profiledString,6454compileString6455);6456if (metaData->startColdPC)6457outputVerboseMMapEntry(6458compilee,6459date,6460time,6461reinterpret_cast<void *>(metaData->startColdPC),6462reinterpret_cast<void *>(metaData->endPC),6463fmtEOL,6464profiledString,6465compileString6466);6467}6468#endif // ifdef TR_HOST_S39064696470// work around spill issue on this method6471#if defined(TR_HOST_S390)6472#pragma option_override(TR::CompilationInfo::compile(J9VMThread *, TR_MethodToBeCompiled *, bool), "OPT(SPILL,256)")6473#endif64746475#if defined(J9VM_INTERP_AOT_RUNTIME_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))6476TR_MethodMetaData *6477TR::CompilationInfoPerThreadBase::installAotCachedMethod(6478J9VMThread *vmThread,6479const void *aotCachedMethod,6480J9Method *method,6481TR_FrontEnd *fe,6482TR::Options *options,6483TR_ResolvedMethod *compilee,6484TR_MethodToBeCompiled *entry,6485TR::Compilation *compiler6486)6487{6488// This function assumes that compilation monitor is released coming in. This is to allow relocations6489// to be able to grow code caches. We also assume the queue slot monitor to be released coming in.64906491if (entry)6492TR_ASSERT(method == entry->getMethodDetails().getMethod(), "assertion failure");64936494// We need to perform the relocation for the method in the shared classes cache6495TR::CodeCache *aotMCCRuntimeCodeCache = NULL;64966497const J9JITDataCacheHeader *cacheEntry = static_cast<const J9JITDataCacheHeader *>(aotCachedMethod);6498if (entry)6499TR_ASSERT(entry->_oldStartPC == 0, "assertion failure"); // we only locate first time compilations65006501TR_MethodMetaData *metaData;6502int32_t returnCode = 0;65036504if (_compInfo.getPersistentInfo()->isRuntimeInstrumentationEnabled())6505{6506reloRuntime()->setIsLoading();6507reloRuntime()->initializeHWProfilerRecords(compiler);6508}65096510metaData = reloRuntime()->prepareRelocateAOTCodeAndData(vmThread,6511fe,6512aotMCCRuntimeCodeCache,6513cacheEntry,6514method,6515false,6516options,6517compiler,6518compilee);6519setMetadata(metaData);6520returnCode = reloRuntime()->returnCode();65216522if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))6523TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH,6524"prepareRelocateAOTCodeAndData results: j9method=%p metaData=%p returnCode=%d method=%s",6525method, metaData, returnCode, compiler->signature());65266527if (_compInfo.getPersistentInfo()->isRuntimeInstrumentationEnabled())6528{6529reloRuntime()->resetIsLoading();6530}65316532if (metaData)6533{6534UDATA reloTime = 0;65356536if (TrcEnabled_Trc_JIT_AotLoadEnd)6537{6538PORT_ACCESS_FROM_JITCONFIG(_jitConfig);6539reloTime = j9time_usec_clock() - reloRuntime()->reloStartTime();65406541Trc_JIT_AotLoadEnd(vmThread, compiler->signature(),6542metaData->startPC, metaData->endWarmPC, metaData->startColdPC, metaData->endPC,6543reloTime, method, metaData, _compInfo.getMethodQueueSize(),6544TR::CompilationInfo::getMethodBytecodeSize(method),65450);6546}65476548if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd))6549{6550if (reloTime == 0)6551{6552PORT_ACCESS_FROM_JITCONFIG(_jitConfig);6553reloTime = j9time_usec_clock() - reloRuntime()->reloStartTime();6554}65556556TR_VerboseLog::CriticalSection vlogLock;6557TR_VerboseLog::write(TR_Vlog_COMP, "(AOT load) ");6558CompilationInfo::printMethodNameToVlog(method);6559TR_VerboseLog::write(" @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT, metaData->startPC, metaData->endWarmPC);6560TR_VerboseLog::write(" Q_SZ=%d Q_SZI=%d QW=%d j9m=%p bcsz=%u", _compInfo.getMethodQueueSize(), _compInfo.getNumQueuedFirstTimeCompilations(),6561_compInfo.getQueueWeight(), method, _compInfo.getMethodBytecodeSize(method));65626563if (TR::Options::getVerboseOption(TR_VerbosePerformance))6564{6565TR_VerboseLog::write(" time=%dus", (uint32_t)reloTime);6566}6567if (entry)6568TR_VerboseLog::write(" compThreadID=%d", getCompThreadId());65696570TR_VerboseLog::writeLine("");6571}65726573#if defined(TR_HOST_S390)6574if (TR::Options::getVerboseOption(TR_VerboseMMap))6575{6576TR_J9VMBase *vm = TR_J9VMBase::get(_jitConfig, vmThread);6577TR_ResolvedMethod *compilee = vm->createResolvedMethod(compiler->trMemory(), (TR_OpaqueMethodBlock *)method);6578outputVerboseMMapEntries(compilee, metaData, "AOT ", "load");6579}6580#endif65816582if (J9_EVENT_IS_HOOKED(_jitConfig->javaVM->hookInterface, J9HOOK_VM_DYNAMIC_CODE_LOAD))6583{6584OMR::CodeCacheMethodHeader *ccMethodHeader;6585ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(_jitConfig->javaVM->hookInterface, vmThread, method, (U_8*)metaData->startPC, metaData->endWarmPC - metaData->startPC, "JIT warm body", metaData);6586if (metaData->startColdPC)6587{6588// Register the cold code section too6589//6590ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(_jitConfig->javaVM->hookInterface, vmThread, method, (U_8*)metaData->startColdPC, metaData->endPC - metaData->startColdPC, "JIT cold body", metaData);6591}6592ccMethodHeader = getCodeCacheMethodHeader((char *)metaData->startPC, 32, metaData);6593if (ccMethodHeader && (metaData->bodyInfo != NULL))6594{6595J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get((void *)metaData->startPC);6596if (linkageInfo->isRecompMethodBody())6597{6598ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(_jitConfig->javaVM->hookInterface, vmThread, method, (U_8 *)((char*)ccMethodHeader->_eyeCatcher+4), metaData->startPC - (UDATA)((char*)ccMethodHeader->_eyeCatcher+4), "JIT method header", metaData);6599}6600}6601}66026603++_compInfo._statNumMethodsFromSharedCache;6604}6605else // relocation failed6606{6607if (entry)6608{6609entry->_compErrCode = returnCode;6610entry->setAotCodeToBeRelocated(NULL); // reset if relocation failed6611entry->_tryCompilingAgain = _compInfo.shouldRetryCompilation(entry, compiler); // this will set entry->_doNotUseAotCodeFromSharedCache = true;66126613// Feature [Defect 172216/180384]: Implement hints for failed AOT validations. The idea is that the failed validations are due to the6614// fact that AOT methods are loaded at a lower count than when they were compiled so the JVM is given less opportunity to resolve things.6615// The new hint tells us that a previous relocation failed a validation so specify a higher scount for the next run to give it more chance6616// to resolve things.6617switch (returnCode)6618{6619case compilationAotValidateFieldFailure:6620case compilationAotStaticFieldReloFailure:6621case compilationAotClassReloFailure:6622if ((options->getInitialBCount() != 0) &&6623(options->getInitialCount() != 0))6624{6625TR_J9SharedCache *sc = (TR_J9SharedCache *) (compiler->fej9()->sharedCache());6626sc->addHint(method, TR_HintFailedValidation);6627}6628break;6629}6630}6631}6632return metaData;6633}6634#endif // defined(J9VM_INTERP_AOT_RUNTIME_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))66356636//--------------- queueAOTUpgrade ----------6637// The entry currently being processed will be cloned with the clone being an upgrade6638// request (which will be performed at cold).6639// The j9method currently being compiled, must have been compiled successfully because we use its startPC.6640// This routine must be called with compilationMonitor in hand.6641// This routine is normally invoked by the compilation thread.6642// I think we can avoid scanning the queue for a duplicate because such a duplicate cannot exist6643// long as the original is still being processed.6644//-----------------------------------------6645void TR::CompilationInfo::queueForcedAOTUpgrade(TR_MethodToBeCompiled *originalEntry, uint16_t hints, TR_FrontEnd *fe)6646{6647#if defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390))66486649TR_ASSERT(!originalEntry->isDLTCompile(), "No DLTs allowed in queueForcedAOTUpgrade"); // no DLT here6650TR_ASSERT(originalEntry->_compInfoPT && originalEntry->_compInfoPT->_methodBeingCompiled == originalEntry, "assertion failure");6651// This must be an AOT load6652if (!TR::Options::getCmdLineOptions()->allowRecompilation())6653return;66546655// TODO: if this is already available, pass it as a parameter6656TR_PersistentMethodInfo *methodInfo = TR::Recompilation::getMethodInfoFromPC(originalEntry->_newStartPC);6657if (!methodInfo)6658return;66596660// If quickstart and we are in startup phase, do not perform the6661// upgrade hints for some methods that we know are memory expensive6662if (TR::Options::isQuickstartDetected() && // TODO: we may want to apply the same logic for server mode as well6663_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP)6664{6665if (hints & TR_HintLargeMemoryMethodC)6666return; // Don't want to increase the footprint6667}66686669// Search for an empty entry in the methodPool.6670TR_MethodToBeCompiled *cur = getCompilationQueueEntry();6671if (!cur)6672return;66736674// must create a new optimization plan6675TR_Hotness hotness = cold;6676bool doProfiling = false;6677if (hints & TR_HintScorching)6678{6679hotness = veryHot;6680doProfiling = !TR::Options::getCmdLineOptions()->getOption(TR_DisableProfiling) &&6681!methodInfo->profilingDisabled();6682}6683else if (hints & TR_HintHot)6684{6685hotness = hot;6686}6687else // See if we should upgrade at warm6688{6689// Do not upgrade at warm if the compilation is known to take a lot of memory or CPU6690// and we are in startup phase6691if (_jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP || !(hints & (TR_HintLargeMemoryMethodW | TR_HintLargeCompCPUW)))6692{6693if (!TR::Options::isQuickstartDetected())6694hotness = warm;6695else if (TR::Options::getCmdLineOptions()->getOption(TR_UpgradeBootstrapAtWarm))// This is a JIT option because it pertains to JIT compilations6696{6697// To reduce affect on short applications like tomcat6698// upgrades to warm should be performed only outside the grace period6699//if (getPersistentInfo()->getElapsedTime() >= (uint64_t)getPersistentInfo()->getClassLoadingPhaseGracePeriod())6700{6701TR_OpaqueMethodBlock *method = (TR_OpaqueMethodBlock *) originalEntry->getMethodDetails().getMethod();6702TR_J9VMBase *fej9 = (TR_J9VMBase *)fe;6703if (fej9->isClassLibraryMethod(method))6704hotness = warm;6705}6706}6707}6708}6709TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(hotness, doProfiling, true);6710if (!plan) // OOM6711{6712cur->_freeTag = ENTRY_INITIALIZED; // entry must appear as being initialized67136714// put back into the pool6715recycleCompilationEntry(cur);6716return;6717}67186719// Do not mark this compilation as un upgrade; otherwise we would try again to store6720// a hint in the shared cache when the upgrade is complete6721//6722cur->initialize(originalEntry->getMethodDetails(), originalEntry->_newStartPC, CP_ASYNC_BELOW_NORMAL, plan);6723cur->_jitStateWhenQueued = getPersistentInfo()->getJitState();67246725J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(originalEntry->_newStartPC);6726linkageInfo->setIsBeingRecompiled(); // mark that we try to compile it67276728methodInfo->setNextCompileLevel(plan->getOptLevel(), plan->insertInstrumentation());6729methodInfo->setReasonForRecompilation(TR_PersistentMethodInfo::RecompDueToForcedAOTUpgrade);6730_statNumForcedAotUpgrades++;67316732cur->_entryTime = getPersistentInfo()->getElapsedTime(); // cheaper version6733incrementMethodQueueSize(); // one more method added to the queue6734// No need to increment _numQueuedFirstTimeCompilations because this is a recompilation67356736// Must determine the entry weight; let's use something simpler6737// because we know the opt level can be either cold or warm6738// and we know this is not JNI or other thunk6739//6740uint8_t entryWeight; // must be less than 2566741switch (hotness)6742{6743case cold: entryWeight = COLD_WEIGHT; break;6744case warm:6745{6746J9Method *method = originalEntry->getMethodDetails().getMethod();6747J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);6748if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))6749entryWeight = WARM_LOOPY_WEIGHT;6750else6751entryWeight = WARM_LOOPLESS_WEIGHT;6752}6753break;6754case hot: entryWeight = HOT_WEIGHT; break;6755case veryHot: entryWeight = VERY_HOT_WEIGHT; break;6756default: entryWeight = THUNKS_WEIGHT;6757} // end switch67586759cur->_weight = entryWeight;6760_queueWeight += (int32_t)entryWeight; // increase queue weight67616762cur->_async = true;67636764// Do not activate any new compilation thread67656766// Instead of searching for a matching entry, just queue this entry6767// We can away with scanning the queue for duplicates because the original method is still6768// at the head of the queue6769//6770queueEntry(cur);6771//fprintf(stderr, "Forcefully upgraded j9method %p (entry=%p)\n", cur->_method, cur);6772#endif // #if defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390))6773}677467756776// This method is executed by compilation threads at the end of a compilation6777// and needs to be executed with the compQueueMonitor in hand.6778// Prerequisites: getCompilation() and getMetadata() return valid answers6779void6780TR::CompilationInfoPerThreadBase::generatePerfToolEntry()6781{6782#if defined(LINUX)6783TR_ASSERT(getCompilation() && getMetadata(), "generatePerfToolEntry() must be executed only for successful compilations");6784// At this point we have the compilationQueueMonitor so we don't run into concurrency issues6785static bool firstAttempt = true;6786if (firstAttempt)6787{6788firstAttempt = false;6789uintptr_t jvmPid = getCompilation()->fej9()->getProcessID();6790static const int maxPerfFilenameSize = 15 + sizeof(jvmPid)* 3; // "/tmp/perf-%ld.map"6791char perfFilename[maxPerfFilenameSize] = { 0 };67926793bool truncated = TR::snprintfTrunc(perfFilename, maxPerfFilenameSize, "/tmp/perf-%ld.map", jvmPid);6794if (!truncated)6795{6796TR::CompilationInfoPerThreadBase::_perfFile = j9jit_fopen(perfFilename, "a", true);6797}6798if (!getPerfFile()) // couldn't open the file6799{6800if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompFailure))6801TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, "t=%u WARNING: Cannot open perf tool file: %s",6802(uint32_t)_compInfo.getPersistentInfo()->getElapsedTime(), perfFilename); // even if snprintf failed above we should still be ok.6803// Do we want a message without verbose log being specified?6804}6805}6806if (getPerfFile())6807{6808j9jit_fprintf(getPerfFile(), "%p %lX %s_%s\n", getMetadata()->startPC, getMetadata()->endWarmPC - getMetadata()->startPC,6809getCompilation()->signature(), getCompilation()->getHotnessName(getCompilation()->getMethodHotness()));6810// If there is a cold section, add another line6811if (getMetadata()->startColdPC)6812{6813j9jit_fprintf(getPerfFile(), "%p %lX %s_%s\n", getMetadata()->startColdPC, getMetadata()->endPC - getMetadata()->startColdPC,6814getCompilation()->signature(), getCompilation()->getHotnessName(getCompilation()->getMethodHotness())); // should we change the name of the method?6815}6816// Flushing degrades performance, but ensures that we have the data6817// written even if the JVM is abruptly terminated6818j9jit_fflush(getPerfFile());6819}6820#endif6821}68226823const void*6824TR::CompilationInfoPerThreadBase::findAotBodyInSCC(J9VMThread *vmThread, const J9ROMMethod *romMethod)6825{6826#if defined(J9VM_INTERP_AOT_RUNTIME_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))6827#if defined(J9VM_OPT_JITSERVER)6828TR_ASSERT(!TR::CompilationInfo::getStream(), "This function should not be called at the server because SCC does not exist at the server.");6829#endif /* defined(J9VM_OPT_JITSERVER) */6830UDATA flags = 0;6831const void *aotCachedMethod = vmThread->javaVM->sharedClassConfig->findCompiledMethodEx1(vmThread, romMethod, &flags);6832if (!(flags & J9SHR_AOT_METHOD_FLAG_INVALIDATED))6833return aotCachedMethod; // possibly NULL6834else6835#endif6836return NULL;6837}68386839bool6840TR::CompilationInfoPerThreadBase::isMethodIneligibleForAot(J9Method *method)6841{6842const J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);6843const J9ROMClass *romClass = J9_CLASS_FROM_METHOD(method)->romClass;6844J9UTF8 *className = J9ROMCLASS_CLASSNAME(romClass);68456846// Don't AOT-compile anything in j/l/i for now6847if (strncmp(utf8Data(className), "java/lang/invoke/", sizeof("java/lang/invoke/") - 1) == 0)6848return true;68496850if (J9UTF8_LENGTH(className) == 36 &&68510 == memcmp(utf8Data(className), "com/ibm/rmi/io/FastPathForCollocated", 36))6852{6853J9UTF8 *utf8 = J9ROMMETHOD_NAME(romMethod);6854if (J9UTF8_LENGTH(utf8) == 21 &&68550 == memcmp(J9UTF8_DATA(utf8), "isVMDeepCopySupported", 21))6856return true;6857}6858return false;6859}68606861#if defined(J9VM_OPT_JITSERVER)68626863bool6864TR::CompilationInfoPerThreadBase::isMemoryCheapCompilation(uint32_t bcsz, TR_Hotness optLevel)6865{6866if (optLevel > warm)6867{6868return false;6869}6870if (optLevel == warm && bcsz > 6) // For bcsz >= 7, scratch_mem can reach 7.5 MB which is deemed too much6871{6872return false;6873}6874// Look at the available resources and decide whether we can afford a local compilation6875// Ideally, we should consider network latency too, but that is too complicated6876//6877bool incompleteInfo = true;6878uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incompleteInfo);6879// If memory information is not available, perform all compilations remotely for safety6880if (freePhysicalMemorySizeB == OMRPORT_MEMINFO_NOT_AVAILABLE || incompleteInfo)6881{6882return false;6883}6884// For very small amounts of free memory, send everything remotely6885if (freePhysicalMemorySizeB < 10 * 1024 * 1024)6886{6887return false;6888}6889if (freePhysicalMemorySizeB < 20 * 1024 * 1024) // 10MB <= freeMem < 20MB6890{6891// Very small methods at cold (expected to take 1MB max)6892return (optLevel <= cold) && (bcsz <= 4);6893}6894if (freePhysicalMemorySizeB < 100 * 1024 * 1024) // 20MB <= freeMem < 100MB6895{6896// All methods at noOpt, very small methods at cold/warm and medium sized methods at cold (expected to take 2.5MB max)6897return (optLevel < cold) || (bcsz <= 4) || (optLevel == cold && bcsz <= 31);6898}6899// freeMem >= 100MB6900// All methods at noOpt/cold and small methods at warm (expected to take 6MB max)6901return true; // Large methods at warm have already been filtered out above6902}69036904bool6905TR::CompilationInfoPerThreadBase::isCPUCheapCompilation(uint32_t bcsz, TR_Hotness optLevel)6906{6907double cpuEntitlement = _compInfo.getJvmCpuEntitlement();6908if (cpuEntitlement < 100.0)6909{6910return false;6911}6912if (cpuEntitlement < 150.0) // [100, 150)6913{6914// Keep local some noOpt/cold compilations6915if (optLevel >= warm || bcsz >= 32)6916{6917return false;6918}6919if (bcsz <= 7) // Small methods at noOpt/cold should be local6920{6921return true;6922}6923// If we have CPU available we could keep local even medium sized cold compilations6924CpuUtilization *cpuUtil = _compInfo.getCpuUtil();6925if (cpuUtil->isFunctional() &&6926_compInfo.getPersistentInfo()->getElapsedTime() >= TR::Options::_classLoadingPhaseInterval && // For first 0.5 sec we don't have valid data6927cpuUtil->getCpuIdle() >= 15 && // There is idle CPU to use6928cpuUtil->getVmCpuUsage() + 15 <= cpuEntitlement) // I am allowed to use 15% more CPU6929return true;6930else6931return false;6932}6933if (cpuEntitlement < 350.0) // [150, 350)6934{6935// Medium sized methods at noOpt/cold6936return (optLevel <= cold) && (bcsz <= 31);6937}69386939// CPU Entitlement >= 350%6940// All noOpt/cold methods and small warm methods6941return (optLevel <= cold) || (bcsz <= 5);6942}69436944bool6945TR::CompilationInfoPerThreadBase::cannotPerformRemoteComp()6946{6947return !JITServer::ClientStream::isServerCompatible(OMRPORT_FROM_J9PORT(_jitConfig->javaVM->portLibrary)) ||6948(!JITServerHelpers::isServerAvailable() && !JITServerHelpers::shouldRetryConnection(OMRPORT_FROM_J9PORT(_jitConfig->javaVM->portLibrary))) ||6949(TR::Compiler->target.cpu.isPower() && _jitConfig->inlineFieldWatches); // Power codegen is missing some FieldWatch relocation support6950}69516952bool6953TR::CompilationInfoPerThreadBase::preferLocalComp(const TR_MethodToBeCompiled *entry)6954{6955// As a heuristic, cold compilations could be performed locally because6956// they are supposed to be cheap with respect to memory and CPU, but6957// only if we think we have enough resources6958//6959if (TR::Options::getCmdLineOptions()->getOption(TR_EnableJITServerHeuristics))6960{6961TR_Hotness optLevel = entry->_optimizationPlan->getOptLevel();6962J9Method *method = entry->getMethodDetails().getMethod();6963uint32_t bcsz = TR::CompilationInfo::getMethodBytecodeSize(method);6964return isMemoryCheapCompilation(bcsz, optLevel) && isCPUCheapCompilation(bcsz, optLevel);6965}6966return false;6967}69686969void6970TR::CompilationInfoPerThreadBase::enterPerClientAllocationRegion()6971{6972// To use per-client memory, this thread must have a cached pointer to the client data6973ClientSessionData *clientData = getClientData();6974if (clientData && clientData->usesPerClientMemory())6975{6976_perClientPersistentMemory = clientData->persistentMemory();6977if (_compiler)6978_compiler->switchToPerClientMemory();6979}6980}69816982void6983TR::CompilationInfoPerThreadBase::exitPerClientAllocationRegion()6984{6985if (_compiler)6986_compiler->switchToGlobalMemory();6987_perClientPersistentMemory = NULL;6988}69896990void6991TR::CompilationInfoPerThreadBase::downgradeLocalCompilationIfLowPhysicalMemory(TR_MethodToBeCompiled *entry)6992{6993TR_ASSERT_FATAL(_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT,6994"Must be called on JITServer client");69956996J9Method *method = entry->getMethodDetails().getMethod();6997if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableJITServerBufferedExpensiveCompilations) &&6998TR::Options::getCmdLineOptions()->allowRecompilation() &&6999!TR::CompilationInfo::isCompiled(method) && // do not downgrade recompilations7000(entry->_optimizationPlan->getOptLevel() >= warm ||7001// AOT compilations that are upgraded back to cheap-warm should be considered expensive7002(entry->_useAotCompilation && !TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableAotAtCheapWarm))))7003{7004// Downgrade a forced local compilation, if the available client memory is low.7005bool incomplete;7006uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incomplete, 10);7007int32_t numActiveThreads = _compInfo.getNumCompThreadsActive();7008if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE &&7009freePhysicalMemorySizeB <= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue() + (numActiveThreads + 4) * TR::Options::getScratchSpaceLowerBound())7010{7011if (TR::Options::isAnyVerboseOptionSet(7012TR_VerboseJITServer,7013TR_VerboseCompilationDispatch,7014TR_VerbosePerformance,7015TR_VerboseCompFailure))7016TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "t=%6u Downgraded a forced local compilation to cold due to low memory: j9method=%p",7017(uint32_t)_compInfo.getPersistentInfo()->getElapsedTime(), method);7018entry->_optimizationPlan->setOptLevel(cold);7019entry->_optimizationPlan->setOptLevelDowngraded(true);7020entry->_optimizationPlan->setDisableGCR(); // disable GCR to prevent aggressive recompilation7021entry->_optimizationPlan->setUseSampling(false); // disable sampling to prevent spontaneous recompilation7022entry->setShouldUpgradeOutOfProcessCompilation(); // ask for an upgrade if the server becomes available7023}7024}7025}7026#endif /* defined(J9VM_OPT_JITSERVER) */70277028/**7029* @brief TR::CompilationInfoPerThreadBase::preCompilationTasks7030* @param vmThread Pointer to the current J9VMThread (input)7031* @param entry Pointer to the TR_MethodToBeCompiled entry (input)7032* @param method Pointer to the J9Method (input)7033* @param aotCachedMethod Pointer to a pointer to the AOT code to be relocated (if it exists) (output)7034* @param trMemory Reference to the TR_Memory associated with this compilation (input)7035* @param canDoRelocatableCompile Reference to a bool; indicates if the current compilation can be AOT compiled (output)7036* @param eligibleForRelocatableCompile Reference to a bool; Indicates if the current compilation is eligible for AOT (output)7037* @param reloRuntime Pointer to a TR_RelocationRuntime; NULL if JVM does not have AOT support (input)7038*7039* This method is used to perform a set of tasks needed before attempting a compilation.7040*7041* This method can throw an exception.7042*/7043void7044TR::CompilationInfoPerThreadBase::preCompilationTasks(J9VMThread * vmThread,7045TR_MethodToBeCompiled *entry,7046J9Method *method,7047const void **aotCachedMethod,7048TR_Memory &trMemory,7049bool &canDoRelocatableCompile,7050bool &eligibleForRelocatableCompile,7051TR_RelocationRuntime *reloRuntime)7052{7053TR_J9VMBase *fe = TR_J9VMBase::get(_jitConfig, vmThread);7054if (NULL == fe)7055throw std::bad_alloc();70567057// Check to see if we find an AOT version in the shared cache7058//7059entry->setAotCodeToBeRelocated(NULL); // make sure decision to load AOT comes from below and not previous compilation/relocation pass7060entry->_doAotLoad = false;70617062#if defined(J9VM_INTERP_AOT_RUNTIME_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))7063if (entry->_methodIsInSharedCache == TR_yes // possible AOT load7064&& !TR::CompilationInfo::isCompiled(method)7065&& !entry->_doNotUseAotCodeFromSharedCache7066&& !TR::Options::getAOTCmdLineOptions()->getOption(TR_NoLoadAOT)7067&& !(_jitConfig->runtimeFlags & J9JIT_TOSS_CODE)7068&& !_jitConfig->inlineFieldWatches)7069{7070// Determine whether the compilation filters allows me to relocate7071// Filters should not be applied to out-of-process compilations7072// because decisions on what needs to be compiled are done at the client7073//7074TR_Debug *debug = TR::Options::getDebug();7075bool canRelocateMethod = true;7076if (debug && !entry->isOutOfProcessCompReq())7077{7078setCompilationShouldBeInterrupted(0); // zero the flag because createResolvedMethod calls7079// acquire/releaseVMaccessIfNeeded and may see the flag set by previous compilation7080TR_FilterBST *filter = NULL;70817082TR_ResolvedMethod *resolvedMethod = fe->createResolvedMethod(&trMemory, (TR_OpaqueMethodBlock *)method);7083if (!debug->methodCanBeRelocated(&trMemory, resolvedMethod, filter) ||7084!debug->methodCanBeCompiled(&trMemory, resolvedMethod, filter))7085canRelocateMethod = false;7086}70877088if (canRelocateMethod && !entry->_oldStartPC)7089{7090// Find the AOT body in the SCC7091//7092*aotCachedMethod = findAotBodyInSCC(vmThread, entry->getMethodDetails().getRomMethod(fe));70937094// Validate the class chain of the class of the method being AOT loaded7095if (*aotCachedMethod && !fe->sharedCache()->classMatchesCachedVersion(J9_CLASS_FROM_METHOD(method)))7096{7097if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))7098{7099TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,7100"Failed to validate the class chain of the class of method %p",7101method);7102}7103*aotCachedMethod = NULL;7104canRelocateMethod = false;7105entry->_doNotUseAotCodeFromSharedCache = true;7106}71077108if (*aotCachedMethod)7109{7110#ifdef COMPRESS_AOT_DATA7111TR_AOTMethodHeader *aotMethodHeader = (TR_AOTMethodHeader*)(((J9JITDataCacheHeader*)*aotCachedMethod) + 1);7112if (aotMethodHeader->flags & TR_AOTMethodHeader_CompressedMethodInCache)7113{7114/**7115* For each AOT compiled method we store in the shareclass cache we have following layout.7116* ---------------------------------------------------------------------------------------7117* | CompiledMethodWrapper | J9JITDataCacheHeader | AOTMethodHeader | Metadata | Codedata|7118* ---------------------------------------------------------------------------------------7119* When we compile and store a method, it stores J9RomMethod for the method in the CompiledMethodWrapper along side7120* size of metadata and codedata in the cache. Now when we request a method from shared class cache7121* it returns address that points to J9JITDataCacheHeader. As while decompressing the data, we need information about7122* the size of original data (We get that information from AOTMethodHeader) and size of deflated data in the cache (Which is stored in7123* CompiledMethodWrapper)7124* So to access data size in shared class cache, we need to access CompiledMethodWrapper.7125*/7126CompiledMethodWrapper *wrapper = ((CompiledMethodWrapper*)(*aotCachedMethod)) - 1;7127int sizeOfCompressedDataInCache = wrapper->dataLength;7128int originalDataSize = aotMethodHeader->compileMethodDataSize + aotMethodHeader->compileMethodCodeSize;7129void *originalData = trMemory.allocateHeapMemory(originalDataSize);7130int aotMethodHeaderSize = sizeof(J9JITDataCacheHeader) + sizeof(TR_AOTMethodHeader);7131memcpy(originalData, *aotCachedMethod, aotMethodHeaderSize);7132if (inflateBuffer((U_8 *)(*aotCachedMethod) + aotMethodHeaderSize, sizeOfCompressedDataInCache - aotMethodHeaderSize, (U_8*)(originalData)+aotMethodHeaderSize, originalDataSize - aotMethodHeaderSize) == DECOMPRESSION_FAILED)7133{7134if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))7135{7136J9UTF8 *className;7137J9UTF8 *name;7138J9UTF8 *signature;7139getClassNameSignatureFromMethod(method, className, name, signature);7140TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "!%.*s.%.*s%.*s : Decompression of method data failed - Compressed Method Size = %d bytes, Stored original method size = %d bytes",7141J9UTF8_LENGTH(className), (char *)J9UTF8_DATA(className),7142J9UTF8_LENGTH(name), (char *)J9UTF8_DATA(name),7143J9UTF8_LENGTH(signature), (char *)J9UTF8_DATA(signature),7144sizeOfCompressedDataInCache, originalDataSize);7145}7146// If we can not inflate the method data, JIT compile the method.7147canRelocateMethod = false;7148*aotCachedMethod = NULL;7149entry->_doNotUseAotCodeFromSharedCache = true;7150}7151else7152{7153if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))7154{7155J9UTF8 *className;7156J9UTF8 *name;7157J9UTF8 *signature;7158getClassNameSignatureFromMethod(method, className, name, signature);7159TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "%.*s.%.*s%.*s : Decompression of method data Successful - Compressed Method Size = %d bytes, Stored original method size = %d bytes",7160J9UTF8_LENGTH(className), (char *)J9UTF8_DATA(className),7161J9UTF8_LENGTH(name), (char *)J9UTF8_DATA(name),7162J9UTF8_LENGTH(signature), (char *)J9UTF8_DATA(signature),7163sizeOfCompressedDataInCache, originalDataSize);7164}7165*aotCachedMethod = originalData;7166}7167}7168if (canRelocateMethod)7169{7170// All conditions are met for doing an AOT load. Mark this fact on the entry.7171entry->_doAotLoad = true;7172entry->setAotCodeToBeRelocated(*aotCachedMethod);7173reloRuntime->setReloStartTime(getTimeWhenCompStarted());7174}7175#else // data compression not supported7176// All conditions are met for doing an AOT load. Mark this fact on the entry.7177entry->_doAotLoad = true;7178entry->setAotCodeToBeRelocated(*aotCachedMethod);7179reloRuntime->setReloStartTime(getTimeWhenCompStarted());7180#endif7181}7182}7183else if (entry->_oldStartPC)7184{7185J9JITExceptionTable *oldMetaData = jitConfig->jitGetExceptionTableFromPC(vmThread, (UDATA)entry->_oldStartPC);7186if (oldMetaData)7187{7188TR_PersistentJittedBodyInfo *oldBodyInfo = (TR_PersistentJittedBodyInfo *)oldMetaData->bodyInfo;7189TR_ASSERT(oldBodyInfo && oldBodyInfo->getIsInvalidated(), "entry is interpreted and has a non-NULL _oldStartPC but the old body has not been invalidated.");7190}7191}7192}7193#if defined(J9VM_OPT_JITSERVER)7194bool cannotDoRemoteCompilation = cannotPerformRemoteComp();7195#endif /* defined(J9VM_OPT_JITSERVER) */71967197if (!entry->isAotLoad()) // We don't/can't relocate this method7198{7199if (TR::Options::getCmdLineOptions()->getOption(TR_ActivateCompThreadWhenHighPriReqIsBlocked))7200{7201// AOT loads that failed may be retried as JIT compilations7202// Such requests inherit the high priority of the AOT load7203// Now that this request is out of the queue we can safely change its7204// priority to a lower value so that when another AOT load comes along7205// a secondary compilation thread will be activated72067207// Is this a JIT retrial of a failed AOT load?7208if (entry->_methodIsInSharedCache == TR_yes && // possible AOT load7209entry->_doNotUseAotCodeFromSharedCache && // transformed into a JIT request7210entry->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS) // because it failed previously7211{7212// Lower priority to CP_ASYNC_NORMAL7213if (entry->_priority > CP_ASYNC_NORMAL)7214entry->_priority = CP_ASYNC_NORMAL;7215}7216}72177218// Determine if we need to perform an AOT compilation7219//7220if (entry->isOutOfProcessCompReq())7221{7222// Since all of the preliminary checks have already been done at the client,7223// eligibleForRelocatableCompile should be true at the server side if the client7224// requests AOT.7225eligibleForRelocatableCompile = entry->_useAotCompilation;7226}7227else7228{7229TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();7230eligibleForRelocatableCompile =72317232// Shared Classes Enabled7233TR::Options::sharedClassCache()72347235// Unsupported compilations7236&& !entry->isJNINative()7237&& !details.isNewInstanceThunk()7238&& !details.isMethodHandleThunk()7239&& !entry->isDLTCompile()72407241// Only generate AOT compilations for first time compiles7242&& !TR::CompilationInfo::isCompiled(method)72437244// If using a loadLimit/loadLimitFile, don't do an AOT compilation7245// for a method body that's already in the SCC7246&& entry->_methodIsInSharedCache != TR_yes72477248// See eclipse-openj9/openj9#11879 for details7249&& (!TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug)7250|| !entry->_oldStartPC)72517252// Eligibility checks7253&& !entry->_doNotUseAotCodeFromSharedCache7254&& fe->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass)7255&& !isMethodIneligibleForAot(method)7256&& (!TR::Options::getAOTCmdLineOptions()->getOption(TR_AOTCompileOnlyFromBootstrap)7257|| fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method), true)72587259// Ensure we can generate a class chain for the class of the7260// method to be compiled7261&& (NULL != fe->sharedCache()->rememberClass(J9_CLASS_FROM_METHOD(method)))72627263// Do not perform AOT compilation if field watch is enabled; there7264// is no benefit to having an AOT body with field watch as it increases7265// the validation complexity, and in case the fields being watched changes,7266// the AOT body cannot be loaded7267&& !_jitConfig->inlineFieldWatches;7268}72697270bool sharedClassTest = eligibleForRelocatableCompile &&7271!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoStoreAOT);72727273bool isSecondAOTRun =7274!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoAotSecondRunDetection) &&7275TR::Options::sharedClassCache() &&7276_compInfo.numMethodsFoundInSharedCache() >= TR::Options::_aotMethodThreshold &&7277_compInfo._statNumAotedMethods <= TR::Options::_aotMethodCompilesThreshold;72787279if (!TR::Options::canJITCompile() && isSecondAOTRun) // detect second AOT run7280{7281if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_ForceAOT))7282TR::CompilationInfo::disableAOTCompilations();7283TR::Options::getCmdLineOptions()->setOption(TR_DisableInterpreterProfiling, true);7284}72857286// Decide if we want an AOT vm or not7287if (sharedClassTest)7288{7289if (TR::Options::getAOTCmdLineOptions()->getOption(TR_ForceAOT) || entry->isOutOfProcessCompReq())7290{7291canDoRelocatableCompile = true;7292}7293else // Use AOT heuristics7294{7295// Heuristic: generate AOT only for downgraded compilations in the first run7296if ((!isSecondAOTRun && entry->_optimizationPlan->isOptLevelDowngraded()) ||7297entry->getMethodDetails().isJitDumpAOTMethod())7298{7299canDoRelocatableCompile = true;7300}7301else7302{7303#if defined(J9VM_OPT_JITSERVER)7304// We also want AOT compilations for JITServer clients that are attached to a7305// JITServer with an AOT cache, because those can be served relatively fast7306if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT &&7307_compInfo.getPersistentInfo()->getJITServerUseAOTCache() && // Ideally we would check if the options allow us to use the AOT cache for this method7308!cannotDoRemoteCompilation) // Make sure remote compilations are possible (no strong guarantees)7309{7310if (!preferLocalComp(entry))7311{7312// Even if this compilation is too expensive to be performed locally,7313// we may still want to refrain from generating too many remote AOT7314// compilations, because of the negative effect of GCR. Smaller methods7315// can be jitted remotely (no AOT) because the server would not save too7316// much CPU by using its AOT cache.7317//7318J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);7319if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ||7320TR::CompilationInfo::getMethodBytecodeSize(method) >= TR::Options::_smallMethodBytecodeSizeThresholdForJITServerAOTCache)7321{7322canDoRelocatableCompile = true;7323}7324}7325}7326#endif /* defined(J9VM_OPT_JITSERVER) */7327}7328}7329}7330}7331#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))73327333// If we are allowed to do relocatable compilations, just do it7334if (canDoRelocatableCompile)7335{7336entry->_useAotCompilation = true;7337#if defined(J9VM_OPT_JITSERVER)7338if (entry->isOutOfProcessCompReq())7339{7340_vm = TR_J9VMBase::get(_jitConfig, vmThread, TR_J9VMBase::J9_SHARED_CACHE_SERVER_VM);7341}7342else7343#endif /* defined(J9VM_OPT_JITSERVER) */7344{7345_vm = TR_J9VMBase::get(_jitConfig, vmThread, TR_J9VMBase::AOT_VM);7346#if defined(J9VM_OPT_JITSERVER)7347if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)7348{7349if (cannotDoRemoteCompilation)7350downgradeLocalCompilationIfLowPhysicalMemory(entry);7351else // AOT compilations are more expensive, so they should all be done remotely7352entry->setRemoteCompReq();7353}7354#endif /* defined(J9VM_OPT_JITSERVER) */7355}7356}7357else if (entry->isOutOfProcessCompReq())7358{7359// JIT compilation on the server side.7360// Its _vm and entry->_useAotCompilation have been set in TR::CompilationInfoPerThreadRemote::processEntry7361TR_ASSERT(!entry->_useAotCompilation, "Client requests AOT compilation but server cannot do remote AOT compilation\n");7362}7363else7364{7365// This is used for JIT compilations and AOT loads on the client side or non-JITServer7366_vm = TR_J9VMBase::get(_jitConfig, vmThread);7367entry->_useAotCompilation = false;7368#if defined(J9VM_OPT_JITSERVER)7369// When both canDoRelocatableCompile and TR::Options::canJITCompile() are false,7370// remote compilation request should not be used.7371if ((_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT) &&7372TR::Options::canJITCompile())7373{7374bool forcedLocal = false;7375bool doLocalCompilation = entry->isAotLoad() || cannotDoRemoteCompilation || preferLocalComp(entry);73767377// If this is a remote sync compilation, change it to a local sync compilation.7378// After the local compilation is completed successfully, a remote async compilation7379// will be scheduled in compileOnSeparateThread().7380TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();7381if (!doLocalCompilation &&7382!entry->_async &&7383!entry->isJNINative() &&7384entry->_optimizationPlan->getOptLevel() > cold &&7385!details.isNewInstanceThunk() &&7386!details.isMethodHandleThunk() &&7387(TR::Options::getCmdLineOptions()->getOption(TR_EnableJITServerHeuristics) ||7388_compInfo.getPersistentInfo()->isLocalSyncCompiles()) &&7389!TR::Options::getCmdLineOptions()->getOption(TR_DisableUpgradingColdCompilations) &&7390TR::Options::getCmdLineOptions()->allowRecompilation())7391{7392doLocalCompilation = true;7393entry->_origOptLevel = entry->_optimizationPlan->getOptLevel();7394entry->_optimizationPlan->setOptLevel(cold);7395entry->_optimizationPlan->setOptLevelDowngraded(true);73967397if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))7398TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "Changed the remote sync compilation to a local sync cold compilation: j9method=%p",7399entry->getMethodDetails().getMethod());7400}74017402if (!doLocalCompilation)7403{7404entry->setRemoteCompReq();7405}7406else if (cannotDoRemoteCompilation)7407{7408downgradeLocalCompilationIfLowPhysicalMemory(entry);7409}7410}7411#endif /* defined(J9VM_OPT_JITSERVER) */7412}7413}74147415/**7416* @brief TR::CompilationInfoPerThreadBase::postCompilationTasks7417* @param vmThread Pointer to the current J9VMThread (input)7418* @param entry Pointer to the TR_MethodToBeCompiled entry (input)7419* @param method Pointer to the J9Method (input)7420* @param aotCachedMethod Pointer to the AOT code to be relocated (if it exists) (input)7421* @param metaData Pointer to the TR_MethodMetaData created on a successful compile (input)7422* @param canDoRelocatableCompile Indicates if the current compilation could be AOT compiled (input)7423* @param eligibleForRelocatableCompile Indicates if the current compilation was eligible for AOT (input)7424* @param reloRuntime Pointer to a TR_RelocationRuntime; NULL if JVM does not have AOT support (input)7425* @return StartPC of the compiled body, NULL if the compilation failed7426*7427* This method is used to perform a set of tasks needed after attempting a compilation; it handles7428* successful and failed compilations, performing the appropriate clean up needed.7429*7430* IMPORTANT: Because this method is called from both the try and catch blocks in7431* TR::CompilationInfoPerThreadBase::compile, an exception should never escape from this method.7432* Calls to this method could be guarded with a try/catch, but that defeats this7433* method's purpose - an escaped exception here would prevent necessary cleanup.7434*/7435void *7436TR::CompilationInfoPerThreadBase::postCompilationTasks(J9VMThread * vmThread,7437TR_MethodToBeCompiled *entry,7438J9Method *method,7439const void *aotCachedMethod,7440TR_MethodMetaData *metaData,7441bool canDoRelocatableCompile,7442bool eligibleForRelocatableCompile,7443TR_RelocationRuntime *reloRuntime)7444{7445#if defined(J9VM_OPT_JITSERVER)7446// JITServer cleanup tasks7447if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)7448{7449((TR::CompilationInfoPerThread*)this)->getClassesThatShouldNotBeNewlyExtended()->clear();7450}7451else if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)7452{7453if (entry->isRemoteCompReq())7454{7455TR::ClassTableCriticalSection commit(_vm);74567457// clear bit for this compilation7458_compInfo.resetCHTableUpdateDone(getCompThreadId());74597460// freshen up newlyExtendedClasses7461auto newlyExtendedClasses = _compInfo.getNewlyExtendedClasses();7462for (auto it = newlyExtendedClasses->begin(); it != newlyExtendedClasses->end();)7463{7464it->second &= _compInfo.getCHTableUpdateDone();7465if (it->second)7466++it;7467else7468it = newlyExtendedClasses->erase(it);7469}7470}7471else // client executing a compilation locally7472{7473// The bit for this compilation thread should be 0 because we never sent any updates to the server7474TR_ASSERT((_compInfo.getCHTableUpdateDone() & (1 << getCompThreadId())) == 0,7475"For local compilations _chTableUpdateFlags should not have the bit set for this comp ID");7476}7477}7478#endif /* defined(J9VM_OPT_JITSERVER) */74797480void *startPC = NULL;7481#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))7482if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableUpdateAOTBytesSize) &&7483metaData && // Compilation succeeded7484!canDoRelocatableCompile && // Non-AOT Compilation7485eligibleForRelocatableCompile && // Was eligible for AOT Compilation7486TR::Options::getAOTCmdLineOptions()->getOption(TR_NoStoreAOT) && // AOT Disabled7487TR_J9SharedCache::isSharedCacheDisabledBecauseFull(&_compInfo) == TR_yes) // AOT Compilation Disabled because SCC is full7488{7489// If the current compilation could have been an AOT compilation7490// had there been space in the SCC, send the code size to the VM7491// so that they can suggest an appropriate size to the user for a7492// subsequent run7493int32_t codeSize = _compInfo.calculateCodeSize(metaData);7494_compInfo.increaseUnstoredBytes(codeSize, 0);7495}7496#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))74977498// We may want to track the CPU time spent by compilation threads periodically7499if (_onSeparateThread)7500{7501TR::CompilationInfoPerThread *cipt = (TR::CompilationInfoPerThread*)this;7502if (cipt->getCompThreadCPU().update() && // returns true if an update happened7503cipt->getCompThreadCPU().isFunctional())7504{7505int32_t CPUmillis = cipt->getCompThreadCPU().getCpuTime() / 1000000;7506// May issue a trace point if enabled7507Trc_JIT_CompCPU(vmThread, getCompThreadId(), CPUmillis);75087509// May issue a message in the vlog if requested7510if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))7511TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u CPU time spent so far in compThread:%d = %d ms",7512(uint32_t)_compInfo.getPersistentInfo()->getElapsedTime(), getCompThreadId(), CPUmillis);7513}7514}75157516// If compilation failed, we must delete any assumptions that might still exist in persistent memory7517if (_compiler && metaData == 0) // compilation failed7518{7519// We may, or may not have metadata7520if (getMetadata())7521{7522getMetadata()->runtimeAssumptionList = NULL;7523}7524}75257526if (_compiler)7527{7528// The KOT needs to survive at least until we're done committing virtual guards and we must not be holding the7529// comp monitor prior to freeing the KOT because it requires VM access.7530if (_compiler->getKnownObjectTable())7531_compiler->freeKnownObjectTable();7532}75337534#if defined(J9VM_OPT_JITSERVER)7535// Do not acquire the compilation monitor on the server, because we do not need7536// it until compilationEnd returns and we do not want to send message from7537// outOfProcessCompilationEnd while holding the monitor7538if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER)7539#endif7540{7541// Re-acquire the compilation monitor so that we can update the J9Method.7542//7543_compInfo.debugPrint(vmThread, "\tacquiring compilation monitor\n");7544_compInfo.acquireCompMonitor(vmThread);7545_compInfo.debugPrint(vmThread, "+CM\n");7546if (_onSeparateThread)7547{7548// Acquire the queue slot monitor now7549//7550_compInfo.debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");7551entry->acquireSlotMonitor(vmThread);7552_compInfo.debugPrint(vmThread, "+AM-", entry);7553}7554}75557556if (TR::CompilationInfo::shouldAbortCompilation(entry, _compInfo.getPersistentInfo()))7557{7558metaData = 0;7559}7560else if (TR::CompilationInfo::shouldRetryCompilation(entry, _compiler))7561{7562startPC = entry->_oldStartPC; // startPC == oldStartPC means compilation failure7563entry->_tryCompilingAgain = true;7564}7565else // compilation will not be retried, either because it succeeded or because we don't want to7566{7567TR_PersistentJittedBodyInfo *bodyInfo;7568void *extra = NULL;7569// JITServer: Can not acquire the jitted body info on the server7570if (!entry->isOutOfProcessCompReq() && entry->isDLTCompile() && !startPC &&7571(extra = TR::CompilationInfo::getPCIfCompiled(method)) && // DLT compilation that failed too many times7572(bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(extra))) // do not use entry->_oldStartPC which is probably 0. Use the most up-to-date startPC7573{7574bodyInfo->getMethodInfo()->setHasFailedDLTCompRetrials(true);7575}75767577startPC = TR::CompilationInfo::compilationEnd(7578vmThread,7579entry->getMethodDetails(),7580jitConfig,7581metaData ? reinterpret_cast<void *>(metaData->startPC) : 0,7582entry->_oldStartPC,7583_vm,7584entry,7585_compiler);75867587if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))7588TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "CompilationEnd returning startPC=%p metadata=%p", startPC, metaData);7589// AOT compilations can fail on purpose because we want to load7590// the AOT body later on. This case is signalled by having a metaData != 07591// but a startPC == entry->_oldStartPC == 07592// For remote compilations at the JITClient we replenish the invocation count in remoteCompilationEnd7593if (metaData && !entry->_oldStartPC && !startPC && !entry->isOutOfProcessCompReq() && !entry->isRemoteCompReq())7594{7595TR_ASSERT(canDoRelocatableCompile, "compilationEnd() can fail only for relocating AOT compilations\n");7596TR_ASSERT(!entry->_oldStartPC, "We expect compilationEnd() to fail only for AOT compilations which are first time compilations\n");75977598TR::CompilationInfo::replenishInvocationCount(method, _compiler);7599}76007601if (!metaData && !entry->_oldStartPC && // First time compilation failed7602!entry->isOutOfProcessCompReq())7603{7604// If we didn't compile the method because filters disallowed it,7605// then do not consider this compilation a failure7606TR_VlogTag vlogTag = (entry->_compErrCode == compilationRestrictedMethod) ? TR_Vlog_INFO : TR_Vlog_FAILURE;7607if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompFailure, TR_VerbosePerformance))7608{7609TR_VerboseLog::CriticalSection vlogLock;7610TR_VerboseLog::write(vlogTag, "Method ");7611CompilationInfo::printMethodNameToVlog(method);7612TR_VerboseLog::writeLine(" will continue as interpreted");7613}7614if (entry->_compErrCode != compilationRestrictedMethod && // do not look at methods excluded by filters7615entry->_compErrCode != compilationExcessiveSize) // do not look at failures due to code cache size7616{7617int32_t numSeriousFailures = _compInfo.incNumSeriousFailures();7618if (numSeriousFailures > TR::Options::_seriousCompFailureThreshold)7619{7620// Generate a trace point7621Trc_JIT_ManyCompFailures(vmThread, numSeriousFailures);7622}7623}7624}76257626if (entry->isAotLoad() && entry->_oldStartPC == 0 && startPC != 0) // AOT load that succeeded7627{7628// We know this is a first time compilation (otherwise we would not attempt an AOT load)7629// Before grabbing the compilation monitor and loading the AOT body7630// let's check the AOT hints (optimistically assuming that the AOT load will succeed)7631if (_onSeparateThread && entry->_async && // KEN need to pass in onSeparateThread?7632(TR::Options::getAOTCmdLineOptions()->getEnableSCHintFlags() & (TR_HintUpgrade | TR_HintHot | TR_HintScorching)))7633{7634// read all hints at once because we may rely on more than just one type7635uint16_t hints = _vm->sharedCache()->getAllEnabledHints(method) & (TR_HintUpgrade | TR_HintHot | TR_HintScorching);7636// Now let's see if we need to schedule an AOT upgrade7637if (hints)7638{7639// must do this before queueing for an upgrade7640entry->_newStartPC = startPC;76417642static char *disableQueueLPQAOTUpgrade = feGetEnv("TR_DisableQueueLPQAOTUpgrade");7643if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableSymbolValidationManager)7644&& !disableQueueLPQAOTUpgrade)7645{7646_compInfo.getLowPriorityCompQueue().addUpgradeReqToLPQ(getMethodBeingCompiled());7647}7648else7649{7650_compInfo.queueForcedAOTUpgrade(entry, hints, _vm);7651}7652}7653}7654}76557656// Check conditions for adding to JProfiling queue.7657// TODO: How should be AOT loads treated?7658if (_addToJProfilingQueue &&7659entry->_oldStartPC == 0 && startPC != 0)// Must be a first time compilation that succeeded7660{7661// Add request to JProfiling Queue7662TR::IlGeneratorMethodDetails details(method);7663getCompilationInfo()->getJProfilingCompQueue().createCompReqAndQueueIt(details, startPC);7664}766576667667if (entry->_compErrCode == compilationOK && _vm->isAOT_DEPRECATED_DO_NOT_USE())7668_compInfo._statNumAotedMethods++;7669}76707671// compilation success can be detected by checking startPC && startPC != _oldStartPC76727673if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableAOTRelocationTiming) && entry->isAotLoad())7674{7675PORT_ACCESS_FROM_JITCONFIG(jitConfig);7676UDATA reloTime = j9time_usec_clock() - reloRuntime->reloStartTime();7677// We have the comp monitor, so the add does not run into sync issues7678_compInfo.setAotRelocationTime(_compInfo.getAotRelocationTime() + reloTime);7679}76807681// Check to see if we need to print compilation information for perf tool on Linux7682if (TR::Options::getCmdLineOptions()->getOption(TR_PerfTool) && _compiler &&7683startPC != 0 && startPC != entry->_oldStartPC)7684{7685generatePerfToolEntry();7686}76877688if (_compiler)7689{7690// Unreserve the code cache used for this compilation7691//7692// NOTE: Although unintuitive, it is possible to reach here without an allocated7693// CodeGenerator. This can happen during AOT loads. See the OMR::Compilation7694// constructor for details.7695//7696if (_compiler->cg() && _compiler->cg()->getCodeCache())7697{7698#if defined(J9VM_OPT_JITSERVER)7699// For JITServer we should wipe this method from the code cache7700if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)7701_compiler->cg()->getCodeCache()->resetCodeCache();7702#endif /* defined(J9VM_OPT_JITSERVER) */7703_compiler->cg()->getCodeCache()->unreserve();7704_compiler->cg()->setCodeCache(0);7705}7706// Unreserve the data cache7707TR_DataCache *dataCache = (TR_DataCache*)_compiler->getReservedDataCache();7708if (dataCache)7709{7710// For AOT compilation failures with an error code of compilationAotCacheFullReloFailure7711// that are going to be retried we want to keep the reservation7712if (entry->_tryCompilingAgain && entry->_compErrCode == compilationAotCacheFullReloFailure)7713{7714TR_ASSERT(canDoRelocatableCompile, "Only AOT compilations can fail with compilationAotCacheFullReloFailure. entry=%p\n", entry);7715_reservedDataCache = dataCache;7716}7717else7718{7719TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);7720_compiler->setReservedDataCache(NULL);7721}7722}7723}7724// Safety net for when the compiler object cannot be created and we have7725// a dataCache reservation from the previous compilation.7726// If we don't intend to retry this compilation, release the cached dataCache7727if (_reservedDataCache && !entry->_tryCompilingAgain)7728{7729TR_DataCacheManager::getManager()->makeDataCacheAvailable(_reservedDataCache);7730_reservedDataCache = NULL;7731}77327733#if defined(J9VM_OPT_JITSERVER)7734if (_compiler7735&& _compiler->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER7736&& !entry->_optimizationPlan->isLogCompilation())7737{7738_compiler->getOptions()->closeLogFileForClientOptions();7739}7740#endif /* defined(J9VM_OPT_JITSERVER) */77417742if (_compiler)7743{7744_compiler->~Compilation();7745}77467747setCompilation(NULL);77487749_vm = NULL;7750_addToJProfilingQueue = false;77517752#if defined(J9VM_OPT_JITSERVER)7753if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)7754{7755// Re-acquire the compilation monitor now that the last message has been sent7756//7757_compInfo.debugPrint(vmThread, "\tacquiring compilation monitor\n");7758_compInfo.acquireCompMonitor(vmThread);7759_compInfo.debugPrint(vmThread, "+CM\n");7760// Acquire the queue slot monitor now7761//7762_compInfo.debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");7763entry->acquireSlotMonitor(vmThread);7764_compInfo.debugPrint(vmThread, "+AM-", entry);7765}7766#endif77677768return startPC;7769}777077717772/**7773* @brief TR::CompilationInfoPerThreadBase::compile7774* @param vmThread Pointer to the current J9VMThread (input)7775* @param entry Pointer to the method to be compiled entry (input)7776* @param scratchSegmentProvider Reference to a J9::J9SegmentProvider (input)7777* @return StartPC of the compiled body, NULL if the compilation failed7778*7779* This is the top level method used to compile a Java method.7780* The compilation thread has VM access when it enters this method though7781* wrappedCompile() may release VM access.7782*/7783void *7784TR::CompilationInfoPerThreadBase::compile(J9VMThread * vmThread,7785TR_MethodToBeCompiled *entry,7786J9::J9SegmentProvider &scratchSegmentProvider)7787{7788TR_ASSERT(!_compiler, "The previous compilation was not properly cleared.");77897790{7791PORT_ACCESS_FROM_JITCONFIG(jitConfig);7792setTimeWhenCompStarted(j9time_usec_clock());7793}77947795TR_MethodMetaData *metaData = NULL;7796void *startPC = NULL;7797const void *aotCachedMethod = NULL;7798J9Method *method = entry->getMethodDetails().getMethod();7799bool canDoRelocatableCompile = false;7800bool eligibleForRelocatableCompile = false;7801bool eligibleForRemoteCompile = false;7802_qszWhenCompStarted = getCompilationInfo()->getMethodQueueSize();78037804TR_RelocationRuntime *reloRuntime = NULL;7805#if defined(J9VM_INTERP_AOT_RUNTIME_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))7806reloRuntime = entry->_compInfoPT->reloRuntime();7807#endif78087809UDATA oldState = vmThread->omrVMThread->vmState;7810vmThread->omrVMThread->vmState = J9VMSTATE_JIT | J9VMSTATE_MINOR;7811vmThread->jitMethodToBeCompiled = method;78127813try7814{7815TR::RawAllocator rawAllocator(vmThread->javaVM);7816J9::SystemSegmentProvider defaultSegmentProvider(78171 << 16,7818(0 != scratchSegmentProvider.getPreferredSegmentSize()) ? scratchSegmentProvider.getPreferredSegmentSize()7819: 1 << 24,7820TR::Options::getScratchSpaceLimit(),7821scratchSegmentProvider,7822rawAllocator7823);7824TR::DebugSegmentProvider debugSegmentProvider(78251 << 16,7826rawAllocator7827);7828TR::SegmentAllocator ®ionSegmentProvider =7829TR::Options::getCmdLineOptions()->getOption(TR_EnableScratchMemoryDebugging) ?7830static_cast<TR::SegmentAllocator &>(debugSegmentProvider) :7831static_cast<TR::SegmentAllocator &>(defaultSegmentProvider);7832TR::Region dispatchRegion(regionSegmentProvider, rawAllocator);78337834// Initialize JITServer's trMemory with per-client persistent memory, since7835// we are guaranteed to be inside a per-client allocation region here.7836TR_Memory trMemory(*TR::Compiler->persistentMemory(), dispatchRegion);78377838preCompilationTasks(vmThread, entry,7839method, &aotCachedMethod, trMemory,7840canDoRelocatableCompile, eligibleForRelocatableCompile,7841reloRuntime);78427843CompileParameters compParam(7844this,7845_vm,7846vmThread,7847reloRuntime,7848entry->_optimizationPlan,7849regionSegmentProvider,7850dispatchRegion,7851trMemory,7852TR::CompileIlGenRequest(entry->getMethodDetails())7853);7854if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))7855TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH,7856"Compilation thread executing compile(): j9method=%p isAotLoad=%d canDoRelocatableCompile=%d eligibleForRelocatableCompile=%d isRemoteCompReq=%d _doNotUseAotCodeFromSharedCache=%d AOTfe=%d isDLT=%d",7857method, entry->isAotLoad(), canDoRelocatableCompile, eligibleForRelocatableCompile, entry->isRemoteCompReq(), entry->_doNotUseAotCodeFromSharedCache, _vm->isAOT_DEPRECATED_DO_NOT_USE(), entry->isDLTCompile());78587859if (7860(TR::Options::canJITCompile()7861|| canDoRelocatableCompile7862|| entry->isAotLoad()7863|| entry->isRemoteCompReq()7864)7865#if defined(TR_HOST_ARM)7866&& !TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug)7867#endif7868)7869{7870// Compile the method7871//78727873PORT_ACCESS_FROM_JITCONFIG(jitConfig);7874_compInfo.debugPrint("\tcompiling method", entry->getMethodDetails(), vmThread);78757876U_32 flags = J9PORT_SIG_FLAG_MAY_RETURN |7877J9PORT_SIG_FLAG_SIGSEGV | J9PORT_SIG_FLAG_SIGFPE |7878J9PORT_SIG_FLAG_SIGILL | J9PORT_SIG_FLAG_SIGBUS | J9PORT_SIG_FLAG_SIGTRAP;78797880uintptr_t result = 0;78817882// Attempt to request a compilation, while guarding against any crashes that occur7883// inside the compile request. For log compilations, simply return.7884//7885uintptr_t protectedResult = 0;7886if (entry->getMethodDetails().isJitDumpMethod())7887{7888TR::CompilationInfoPerThreadBase::UninterruptibleOperation jitDumpRecompilation(*this);78897890protectedResult = j9sig_protect(wrappedCompile, static_cast<void*>(&compParam),7891jitDumpSignalHandler,7892vmThread, flags, &result);7893}7894else7895{7896protectedResult = j9sig_protect(wrappedCompile, static_cast<void*>(&compParam),7897jitSignalHandler,7898vmThread, flags, &result);7899}79007901metaData = (protectedResult == 0) ? reinterpret_cast<TR_MethodMetaData *>(result) : NULL;7902}7903else7904{7905entry->_compErrCode = compilationRestrictedMethod;7906}79077908// This method has to be called from within the try block,7909// otherwise, the TR_Memory, TR::Region, and TR::SegmentAllocator7910// objects go out of scope and get destroyed.7911startPC = postCompilationTasks(vmThread, entry, method,7912aotCachedMethod, metaData,7913canDoRelocatableCompile, eligibleForRelocatableCompile,7914reloRuntime);7915}7916catch (const std::exception &e)7917{7918entry->_compErrCode = compilationFailure;79197920if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))7921{7922try7923{7924throw;7925}7926catch (const J9::JITShutdown)7927{7928TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: JIT Shutdown signaled>");7929}7930catch (const std::bad_alloc &e)7931{7932TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: out of scratch memory>");7933}7934catch (const std::exception &e)7935{7936TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: compilation aborted>");7937}7938}79397940Trc_JIT_outOfMemory(vmThread);79417942// Compilation object has already been deallocated by this point7943// due to heap memory region going out of scope7944TR_ASSERT_FATAL(getCompilation() == NULL, "Compilation must be deallocated and NULL by this point");79457946// This method has to be called from within the catch block,7947// since moving it outside would result in it getting invoked7948// twice on a successful compilation.7949startPC = postCompilationTasks(vmThread, entry, method,7950aotCachedMethod, metaData,7951canDoRelocatableCompile, eligibleForRelocatableCompile,7952reloRuntime);7953}795479557956vmThread->omrVMThread->vmState = oldState;7957vmThread->jitMethodToBeCompiled = NULL;79587959return startPC;7960}79617962// static method7963TR_MethodMetaData *7964TR::CompilationInfoPerThreadBase::wrappedCompile(J9PortLibrary *portLib, void * opaqueParameters)7965{7966CompileParameters * p = static_cast<CompileParameters *>(opaqueParameters);7967TR::Compilation * volatile compiler = 0;7968TR::Options *options = 0;7969TR_ResolvedMethod *compilee = 0;79707971TR::CompilationInfoPerThreadBase *that = p->_compilationInfo; // static method, no this7972TR_J9VMBase *vm = p->_vm;7973J9VMThread *vmThread = p->_vmThread;79747975TR_RelocationRuntime *reloRuntime = p->_reloRuntime;79767977J9JITConfig *jitConfig = that->_jitConfig;7978bool reducedWarm = false;79797980TR::SegmentAllocator &scratchSegmentProvider = p->_scratchSegmentProvider;79817982// cleanup the compilationShouldBeInterrupted flag.7983that->setCompilationShouldBeInterrupted(0);7984that->setMetadata(NULL);79857986try7987{7988if (that->_methodBeingCompiled->isDLTCompile())7989{7990TR_J9SharedCache *sc = (TR_J9SharedCache *) (vm->sharedCache());7991if (sc)7992sc->addHint(that->_methodBeingCompiled->getMethodDetails().getMethod(), TR_HintDLT);7993}79947995InterruptibleOperation generatingCompilationObject(*that);7996TR::IlGeneratorMethodDetails & details = that->_methodBeingCompiled->getMethodDetails();7997TR_OpaqueMethodBlock *method = (TR_OpaqueMethodBlock *) details.getMethod();79987999// Create the compilee8000if (details.isMethodHandleThunk())8001{8002J9::MethodHandleThunkDetails &mhDetails = static_cast<J9::MethodHandleThunkDetails &>(details);8003compilee = vm->createMethodHandleArchetypeSpecimen(p->trMemory(), method, mhDetails.getHandleRef());8004TR_ASSERT(compilee, "Cannot queue a thunk compilation for a MethodHandle without a suitable archetype");8005}8006else if (details.isNewInstanceThunk())8007{8008J9::NewInstanceThunkDetails &niDetails = static_cast<J9::NewInstanceThunkDetails &>(details);8009compilee = vm->createResolvedMethod(p->trMemory(), method, NULL, (TR_OpaqueClassBlock *) niDetails.classNeedingThunk());8010}8011else8012{8013compilee = vm->createResolvedMethod(p->trMemory(), method);8014}80158016if (that->_methodBeingCompiled->_optimizationPlan->isUpgradeRecompilation())8017{8018// TR_ASSERT(that->_methodBeingCompiled->_oldStartPC, "upgrade recompilations must have some oldstartpc");8019// In JITServer mode, it doesn't have to.8020TR_PersistentJittedBodyInfo *bodyInfo = ((TR_ResolvedJ9Method*)compilee)->getExistingJittedBodyInfo();8021if (bodyInfo->getIsAotedBody() || bodyInfo->getHotness() <= cold)8022{8023TR_J9SharedCache *sc = (TR_J9SharedCache *) (vm->sharedCache());8024if (sc)8025sc->addHint(that->_methodBeingCompiled->getMethodDetails().getMethod(), TR_HintUpgrade);8026}8027}80288029// See if this method can be compiled and check it against the method8030// filters to see if compilation is to be suppressed.80318032TR_FilterBST *filterInfo = NULL;8033// JITServer: methodCanBeCompiled check should have been done on the client, skip it on the server.8034if (!that->_methodBeingCompiled->isOutOfProcessCompReq() && !that->methodCanBeCompiled(p->trMemory(), vm, compilee, filterInfo))8035{8036that->_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;80378038TR::Options *options = TR::Options::getJITCmdLineOptions();8039if (vm->isAOT_DEPRECATED_DO_NOT_USE())8040options = TR::Options::getAOTCmdLineOptions();8041if (options->getVerboseOption(TR_VerboseCompileExclude))8042{8043TR_VerboseLog::writeLineLocked(TR_Vlog_COMPFAIL, "%s j9m=%p cannot be translated compThreadID=%d",8044compilee->signature(p->trMemory()), method, that->getCompThreadId());8045}8046Trc_JIT_noAttemptToJit(vmThread, compilee->signature(p->trMemory()));80478048compilee = 0;8049}8050else if (jitConfig->runtimeFlags & (J9JIT_CODE_CACHE_FULL | J9JIT_DATA_CACHE_FULL))8051{8052// Optimization to disable future first time compilations from reaching the queue8053that->getCompilationInfo()->getPersistentInfo()->setDisableFurtherCompilation(true);80548055if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))8056{8057TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u <WARNING: JIT CACHES FULL> Disable further compilation",8058(uint32_t)that->getCompilationInfo()->getPersistentInfo()->getElapsedTime());8059}8060if (jitConfig->runtimeFlags & J9JIT_CODE_CACHE_FULL)8061Trc_JIT_cacheFull(vmThread);8062if (jitConfig->runtimeFlags & J9JIT_DATA_CACHE_FULL)8063Trc_JIT_dataCacheFull(vmThread);8064that->_methodBeingCompiled->_compErrCode = compilationExcessiveSize;8065compilee = 0;8066}8067else8068{8069int32_t optionSetIndex = filterInfo ? filterInfo->getOptionSet() : 0;8070int32_t lineNumber = filterInfo ? filterInfo->getLineNumber() : 0;80718072TR_ASSERT(p->_optimizationPlan, "Must have an optimization plan");80738074#if defined(J9VM_OPT_JITSERVER)8075// If the options come from a remote party, skip the setup options process80768077if (that->_methodBeingCompiled->isOutOfProcessCompReq())8078{8079auto compInfoPTRemote = static_cast<TR::CompilationInfoPerThreadRemote *>(that);8080TR_ASSERT_FATAL(compInfoPTRemote->getClientOptions(), "client options must be set for an out-of-process compilation");8081options = TR::Options::unpackOptions(compInfoPTRemote->getClientOptions(), compInfoPTRemote->getClientOptionsSize(), that, vm, p->trMemory());8082if (!p->_optimizationPlan->isLogCompilation())8083{8084options->setLogFileForClientOptions();8085}8086else8087{8088// For JitDump compilations, set the log file to the jitdump file,8089// which has already been created by a thread running JitDump8090TR::Options::findOrCreateDebug();8091options->setLogFile(p->_optimizationPlan->getLogCompilation());8092}8093// The following is a hack to prevent the JITServer from allocating8094// a sentinel entry for the list of runtime assumptions kept in the compiler object8095options->setOption(TR_DisableFastAssumptionReclamation);8096}8097else8098#endif /* defined(J9VM_OPT_JITSERVER) */8099{8100#if defined(J9VM_OPT_JITSERVER)8101// JITServer: we want to suppress log file for client mode8102// Client will get the log files from server.8103if (that->_methodBeingCompiled->isRemoteCompReq())8104{8105TR::Options::suppressLogFileBecauseDebugObjectNotCreated();8106}8107TR_ASSERT(!that->_methodBeingCompiled->isOutOfProcessCompReq(), "JITServer should not change options passed by client");8108#endif /* defined(J9VM_OPT_JITSERVER) */81098110bool aotCompilationReUpgradedToWarm = false;8111if (that->_methodBeingCompiled->_useAotCompilation)8112{8113// In some circumstances AOT compilations are performed at warm8114if ((TR::Options::getCmdLineOptions()->getAggressivityLevel() == TR::Options::AGGRESSIVE_AOT ||8115that->getCompilationInfo()->importantMethodForStartup((J9Method*)method) ||8116(!TR::Compiler->target.cpu.isPower() && // Temporary change until we figure out the AOT bug on PPC8117!TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableAotAtCheapWarm))) &&8118p->_optimizationPlan->isOptLevelDowngraded() &&8119p->_optimizationPlan->getOptLevel() == cold // Is this test really needed?8120#if defined(J9VM_OPT_JITSERVER)8121// Do not reupgrade a compilation that was downgraded due to low memory8122&& (TR::Options::getCmdLineOptions()->getOption(TR_DisableJITServerBufferedExpensiveCompilations) ||8123!that->_methodBeingCompiled->shouldUpgradeOutOfProcessCompilation())8124#endif8125)8126{8127p->_optimizationPlan->setOptLevel(warm);8128p->_optimizationPlan->setOptLevelDowngraded(false);8129aotCompilationReUpgradedToWarm = true;8130}8131}813281338134TR_PersistentCHTable *cht = that->_compInfo.getPersistentInfo()->getPersistentCHTable();8135if (cht && !cht->isActive())8136p->_optimizationPlan->setDisableCHOpts();81378138// Set up options for this compilation. An option subset might apply8139// to the method, either via an option set index in the limitfile or8140// via a regular expression that matches the method.8141//8142options = new (p->trMemory(), heapAlloc) TR::Options(8143p->trMemory(),8144optionSetIndex,8145lineNumber,8146compilee,8147that->_methodBeingCompiled->_oldStartPC,8148p->_optimizationPlan,8149(vm->isAOT_DEPRECATED_DO_NOT_USE() || that->_methodBeingCompiled->isAotLoad()),8150that->getCompThreadId());8151// JITServer TODO determine if we care to support annotations8152if (that->_methodBeingCompiled->isRemoteCompReq())8153{8154options->setOption(TR_EnableAnnotations,false);81558156// This option is used to generate SIMD instructions on Z. Currently the infrastructure8157// to support the relocation of some of those instructions is not available. Thus we disable8158// this option for remote compilations.8159options->setOption(TR_DisableSIMDArrayTranslate);81608161// Infrastructure to support the TOC is currently not available for Remote Compilations. We disable the feature8162// here so that the codegen doesn't generate TOC enabled code as it won't be valid on the client JVM.8163options->setOption(TR_DisableTOC);8164}8165// Determine if known annotations exist and if so, keep annotations enabled8166if (!that->_methodBeingCompiled->isAotLoad() && !vm->isAOT_DEPRECATED_DO_NOT_USE() && options->getOption(TR_EnableAnnotations))8167{8168if (!TR_AnnotationBase::scanForKnownAnnotationsAndRecord(&that->_compInfo, details.getMethod(), vmThread->javaVM, vm))8169options->setOption(TR_EnableAnnotations,false);8170}81718172if (vm->canUseSymbolValidationManager() && options->getOption(TR_EnableSymbolValidationManager))8173{8174options->setOption(TR_UseSymbolValidationManager);8175options->setOption(TR_DisableKnownObjectTable);8176}8177else if (!vm->canUseSymbolValidationManager())8178{8179// disable SVM in case it was enabled explicitly with -Xjit:useSymbolValidationManager8180options->setOption(TR_UseSymbolValidationManager, false);8181}81828183// Adjust Options for AOT compilation8184if (vm->isAOT_DEPRECATED_DO_NOT_USE())8185{8186// Disable dynamic literal pool for AOT because of an unresolved data snippet patching issue in which8187// the "Address Of Ref. Instruction" in the unresolved data snippet points to the wrong load instruction8188options->setOption(TR_DisableOnDemandLiteralPoolRegister);81898190options->setOption(TR_DisableIPA);8191options->setOption(TR_DisableEDO);8192options->setDisabled(OMR::invariantArgumentPreexistence, true);8193options->setOption(TR_DisableHierarchyInlining);8194if (options->getInitialBCount() == 0 || options->getInitialCount() == 0)8195options->setOption(TR_DisableDelayRelocationForAOTCompilations, true);81968197// Perform less inlining if we artificially upgraded this AOT compilation to warm8198if (aotCompilationReUpgradedToWarm)8199options->setInlinerOptionsForAggressiveAOT();82008201TR_ASSERT(vm->isAOT_DEPRECATED_DO_NOT_USE(), "assertion failure");82028203// Do not delay relocations for JITServer client when server side AOT caching is used (gives better performance)8204// Testing the presence of the deserializer is sufficient, because the deserializer8205// is only created at the client and only if server side AOT caching is enabled8206#if defined(J9VM_OPT_JITSERVER)8207if (that->getCompilationInfo()->getJITServerAOTDeserializer())8208options->setOption(TR_DisableDelayRelocationForAOTCompilations);8209#endif /* defined(J9VM_OPT_JITSERVER) */8210}82118212if (that->_methodBeingCompiled->_optimizationPlan->disableCHOpts())8213options->disableCHOpts();82148215if (that->_methodBeingCompiled->_optimizationPlan->disableGCR())8216options->setOption(TR_DisableGuardedCountingRecompilations);82178218if (that->_methodBeingCompiled->_optimizationPlan->getDisableEDO())8219options->setOption(TR_DisableEDO);82208221if (options->getOption(TR_DisablePrexistenceDuringGracePeriod))8222{8223if (that->getCompilationInfo()->getPersistentInfo()->getElapsedTime() < that->getCompilationInfo()->getPersistentInfo()->getClassLoadingPhaseGracePeriod())8224options->setDisabled(OMR::invariantArgumentPreexistence, true);8225}82268227// RI Based Reduced Warm Compilation8228if (p->_optimizationPlan->isHwpDoReducedWarm())8229{8230options->setLocalAggressiveAOT();8231}82328233// The following tweaks only apply for java compilations8234if (!that->_methodBeingCompiled->isAotLoad()) // exclude AOT loads8235{8236J9Method *method = details.getMethod();8237// See if we need to profile first level compilations and if we can do it, change the optimization plan8238//8239if(options->getOption(TR_FirstLevelProfiling) &&8240!that->_methodBeingCompiled->isDLTCompile() && // filter out DLTs8241!that->_methodBeingCompiled->isJNINative() &&8242!that->_methodBeingCompiled->getMethodDetails().isNewInstanceThunk() &&8243that->_methodBeingCompiled->_oldStartPC == 0 && // first time compilations8244TR::CompilationController::getCompilationStrategy()->enableSwitchToProfiling() &&8245options->canJITCompile() &&8246!options->getOption(TR_DisableProfiling) &&8247!options->getOption(TR_NoRecompile) &&8248options->allowRecompilation() && // don't do it for fixed opt level8249p->_optimizationPlan->isOptLevelDowngraded()) // only for classLoadPhase8250// should we do it for bootstrap classes?8251{8252p->_optimizationPlan->setInsertInstrumentation(true);8253p->_optimizationPlan->setUseSampling(false);8254options->setOption(TR_QuickProfile); // to reduce the frequency/count for profiling to 100/28255}82568257// Check if user allows us to do samplingJProfiling.8258// If so, enable it programmatically on a method by method basis8259//8260if (!options->getOption(TR_DisableSamplingJProfiling))8261{8262// Check other preconditions8263if (!TR::CompilationInfo::isCompiled((J9Method*)method) &&8264// GCR is needed for moving away from profiling8265!options->getOption(TR_DisableGuardedCountingRecompilations) &&8266// recompilation must be allowed to move away from profiling8267options->allowRecompilation() && !options->getOption(TR_NoRecompile) &&8268// exclude newInstance, methodHandle8269(details.isOrdinaryMethod() || (details.isMethodInProgress() && options->getOption(TR_UseSamplingJProfilingForDLT))) &&8270// exclude natives8271!TR::CompilationInfo::isJNINative((J9Method*)method))8272// TODO: should we prevent SamplingJProfiling for AOT bodies?8273{8274// Check which heuristic is enabled8275if (options->getOption(TR_UseSamplingJProfilingForAllFirstTimeComps))8276{8277// Enable SamplingJprofiling8278options->setDisabled(OMR::samplingJProfiling, false);8279}8280if (options->getOption(TR_UseSamplingJProfilingForLPQ) &&8281that->_methodBeingCompiled->_reqFromSecondaryQueue)8282{8283// Enable SamplingJProfiling8284options->setDisabled(OMR::samplingJProfiling, false);8285// May want adjust the GCR count;8286// TODO: Estimate the initial invocation count and subtract the current8287// invocation count; this is how many invocations I am missing.8288// Complication: interpreter sampling may have decremented the invocation count further.8289options->setGCRCount(500); // add 500 more invocations8290}8291if (options->getOption(TR_UseSamplingJProfilingForDLT) &&8292(details.isMethodInProgress() || p->_optimizationPlan->isInducedByDLT()))8293{8294// Enable SamplingJProfiling8295options->setDisabled(OMR::samplingJProfiling, false);8296}8297if (options->getOption(TR_UseSamplingJProfilingForInterpSampledMethods))8298{8299int32_t skippedCount = that->getCompilationInfo()->getInterpSamplTrackingInfo()->findAndDelete(method);8300if (skippedCount > 0)8301{8302// Enable SamplingJProfiling8303options->setDisabled(OMR::samplingJProfiling, false);8304// Determine the count8305// Determine entry weight8306J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);8307if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))8308{8309// Don't set a count too high for loopy methods8310options->setGCRCount(std::min(250, skippedCount));8311}8312else8313{8314options->setGCRCount(std::min(1000, skippedCount));8315}8316//fprintf(stderr, "skipped count=%d\n", skippedCount);8317}8318}83198320// When using SamplingJProfiling downgrade to cold to avoid overhead8321//8322if (!options->isDisabled(OMR::samplingJProfiling) &&8323// Check whether we are allowed to downgrade8324!options->getOption(TR_DontDowngradeToCold))8325{8326p->_optimizationPlan->setOptLevel(cold);8327p->_optimizationPlan->setDowngradedDueToSamplingJProfiling(true);8328options->setOptLevel(cold);8329// TODO: should we disable sampling to prevent upgrades before the method collects enough profiling info?8330}8331}8332}83338334bool doJProfile = false;8335if (that->_methodBeingCompiled->_reqFromJProfilingQueue)8336{8337doJProfile = true;8338if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))8339TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Processing req from JPQ", (uint32_t)that->getCompilationInfo()->getPersistentInfo()->getElapsedTime());8340}8341else8342{8343// Is this request a candidate for JProfiling?8344if (TR_JProfilingQueue::isJProfilingCandidate(that->_methodBeingCompiled, options, vm))8345{8346static char *disableFilterOnJProfiling = feGetEnv("TR_DisableFilterOnJProfiling");8347// Apply the filter based on time8348if (disableFilterOnJProfiling)8349{8350doJProfile = true;8351}8352else if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP ||8353that->getCompilationInfo()->getPersistentInfo()->getJitState() == STARTUP_STATE)8354{8355// We want to JProfile this method, but maybe not just now8356if (that->getCompilationInfo()->canProcessJProfilingRequest())8357{8358doJProfile = true;8359}8360else8361{8362that->_addToJProfilingQueue = true;8363// Since we are going to recompile this method based on8364// the JProfiling queue, disable any GCR recompilation8365options->setOption(TR_DisableGuardedCountingRecompilations);8366}8367}8368}8369}83708371// JProfiling may be enabled if TR_EnableJProfilingInProfilingCompilations is set and its a profiling compilation.8372// See optimizer/JProfilingBlock.cpp8373if (!doJProfile)8374{8375options->setOption(TR_EnableJProfiling, false);8376}8377else // JProfiling bodies should not use GCR trees8378{8379options->setOption(TR_DisableGuardedCountingRecompilations);8380}83818382if (that->_methodBeingCompiled->_oldStartPC != 0)8383{8384TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(that->_methodBeingCompiled->_oldStartPC);8385if (bodyInfo)8386{8387TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();8388if (methodInfo->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToInlinedMethodRedefinition)8389methodInfo->incrementNumberOfInlinedMethodRedefinition();8390if (methodInfo->getNumberOfInlinedMethodRedefinition() >= 2)8391options->setOption(TR_DisableNextGenHCR);8392}8393}83948395// Strategy tweaks during STARTUP and IDLE8396//8397if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP ||8398that->getCompilationInfo()->getPersistentInfo()->getJitState() == IDLE_STATE)8399{8400// Disable idiomRecognition during startup of -Xquickstart runs to save memory8401if (TR::Options::isQuickstartDetected())8402options->setDisabled(OMR::idiomRecognition, true);84038404if (options->getOptLevel() < warm)8405{8406if (!vm->isAOT_DEPRECATED_DO_NOT_USE())8407{8408// Adjust DumbInliner cutoff parameter as to make it more conservative in constrained situations8409// For AOT we can be more aggressive because the cost is payed only during first run8410options->setDumbInlinerBytecodeSizeCutoff(that->getCompilationInfo()->computeDynamicDumbInlinerBytecodeSizeCutoff(options));8411// Disable rematerialization to cut on compilation costs8412if (!options->getOption(TR_DisableJava8StartupHeuristics))8413options->setDisabled(OMR::rematerialization, true);8414}8415// Increase the trivial inliner max size for 'important methods' (could be bootstrap methods)8416// We could filter by AOT only, or quickstart only8417//if (that->getCompilationInfo()->importantMethodForStartup(method))8418// options->setTrivialInlinerMaxSize(40);8419}84208421// Disable NextGenHCR during Startup Phase, if any of the8422// following is true:8423//8424// - TR_DisableNextGenHCRDuringStartup has been specified, or8425// - this is a DLT compile, or8426// - optLevel is warm or lower, unless8427// TR_EnableStartupNextGenHCRAtAllOpts has been specified8428//8429static char *disableNextGenHCRDuringStartup = feGetEnv("TR_DisableNextGenHCRDuringStartup");8430static char *enableStartupNextGenHCRAtAllOpts = feGetEnv("TR_EnableStartupNextGenHCRAtAllOpts");8431if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP8432&& (disableNextGenHCRDuringStartup8433|| that->_methodBeingCompiled->isDLTCompile()8434|| (options->getOptLevel() <= warm8435&& !enableStartupNextGenHCRAtAllOpts)))8436{8437options->setOption(TR_DisableNextGenHCR);8438}84398440// Do not allow switching to profiling if this is a big app8441//8442if (that->getCompilationInfo()->getPersistentInfo()->getNumLoadedClasses() >= TR::Options::_bigAppThreshold)8443p->_optimizationPlan->setDoNotSwitchToProfiling(true);84448445// Disable optServer for some classes of compilations during STARTUP and IDLE8446//8447if (!options->getOption(TR_NoOptServer) && !options->getOption(TR_DisableSelectiveNoOptServer) && !options->getOption(TR_Server))8448{8449if (that->_methodBeingCompiled->_oldStartPC == 0) // first time compilations8450{8451// sync requests during startup in an asynchronous environment8452if (that->_methodBeingCompiled->_priority >= CP_SYNC_MIN &&8453that->getCompilationInfo()->asynchronousCompilation())8454{8455options->setOption(TR_NoOptServer);8456reducedWarm = true;8457}8458// all first time compilations during startup8459else if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&8460details.isOrdinaryMethod() &&8461!options->getOption(TR_DisableNoServerDuringStartup))8462{8463options->setOption(TR_NoOptServer);8464reducedWarm = true;8465// These guys should be compiled with GCR hooks so that we get the throughput back8466options->setInsertGCRTrees();8467}84688469}8470else // recompilation requests8471{8472// Upgrades from cold need to be cheaper in startup or idle mode8473if (p->_optimizationPlan->isUpgradeRecompilation())8474{8475options->setOption(TR_NoOptServer);8476}8477else // recompilations triggered through GCR need to be cheaper8478{8479// Note that we may have a warm compilation with NoOptServer that has embedded8480// GCR trees to recompile without NoOptServer (thus better generated code)8481// We want to make sure that the recompilation uses server mode in that case8482//8483TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(that->_methodBeingCompiled->_oldStartPC);8484if (bodyInfo->getMethodInfo()->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToGCR)8485{8486if (bodyInfo->getHotness() < options->getOptLevel()) // prevent warm+NoOptServer --> warm+NoOptServer transitions8487{8488options->setOption(TR_NoOptServer);8489}8490}8491}8492}8493}8494} // Strategy tweaks during STARTUP and IDLE8495else8496{8497// Tweak inlining aggressiveness based on time. Only for non-AOT warm compilations and only in Xtune:virtualized mode.8498if (options->getOption(TR_VaryInlinerAggressivenessWithTime))8499{8500int32_t inlAggr = that->getCompilationInfo()->getPersistentInfo()->getInliningAggressiveness();8501if (inlAggr != 100 && options->getOptLevel() == warm && !vm->isAOT_DEPRECATED_DO_NOT_USE() &&8502TR::Options::getCmdLineOptions()->getAggressivityLevel() == TR::Options::AGGRESSIVE_AOT)8503{8504options->setInlinerCGBorderFrequency(9800 - 8 * inlAggr);8505options->setInlinerCGColdBorderFrequency(7500 - 25 * inlAggr);8506options->setInlinerCGVeryColdBorderFrequency(5000 - 35 * inlAggr);8507options->setInlinerBorderFrequency(9000 - 30 * inlAggr);8508options->setInlinerVeryColdBorderFrequency(5500 - 40 * inlAggr);8509if (inlAggr < 25)8510options->setOption(TR_NoOptServer);8511}8512}8513}8514// Do not try any GRA savings at hot and above or if AOT8515if (options->getOption(TR_EnableGRACostBenefitModel))8516{8517if (options->getOptLevel() > warm || vm->isAOT_DEPRECATED_DO_NOT_USE())8518options->setOption(TR_EnableGRACostBenefitModel, false);8519}85208521// Disable AOT w/ SVM during startup8522if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP)8523{8524static char *dontDisableSVMDuringStartup = feGetEnv("TR_DontDisableSVMDuringStartup");8525if (!dontDisableSVMDuringStartup)8526options->setOption(TR_UseSymbolValidationManager, false);8527}85288529// See if we need to insert GCR trees8530if (!details.supportsInvalidation() ||8531options->getOptLevel() >= hot) // Workaround for a bug with GCR inserted in hot bodies. See #4549 for details.8532{ // Upgrades hot-->scorching should be done through sampling, not GCR8533options->setOption(TR_DisableGuardedCountingRecompilations);8534}8535else if (vm->isAOT_DEPRECATED_DO_NOT_USE() || (options->getOptLevel() < warm &&8536!(that->_methodBeingCompiled->_jitStateWhenQueued == IDLE_STATE && that->getCompilationInfo()->getPersistentInfo()->getJitState() == IDLE_STATE)))8537{8538options->setInsertGCRTrees(); // This is a recommendation not a directive8539}8540// Disable some expensive optimizations8541if (options->getOptLevel() <= warm && !options->getOption(TR_EnableExpensiveOptsAtWarm))8542{8543options->setOption(TR_DisableStoreSinking);8544}8545} // end of compilation strategy tweaks for Java854685478548// If we are at the last retrial and the automatic logging feature is turned on8549// set TR_TraceAll options to generate a full log file for this compilation8550// (just in case it fails again). Note that the log file must be specified.8551//8552if (options->getOption(TR_EnableLastCompilationRetrialLogging) &&8553(that->_methodBeingCompiled->_compilationAttemptsLeft == 1))8554{8555if (options->getLogFile() != NULL)8556options->setOption(TR_TraceAll);8557}85588559TR_ASSERT(TR::comp() == NULL, "there seems to be a current TLS TR::Compilation object %p for this thread. At this point there should be no current TR::Compilation object", TR::comp());85608561// Under -Xtune:throughput we allow huge methods for compilations above warm8562if (TR::Options::getAggressivityLevel() == TR::Options::TR_AggresivenessLevel::AGGRESSIVE_THROUGHPUT &&8563options->getOptLevel() > warm &&8564!options->getOption(TR_ProcessHugeMethods))8565{8566static char *dontAcceptHugeMethods = feGetEnv("TR_DontAcceptHugeMethods");8567if (!dontAcceptHugeMethods)8568{8569options->setOption(TR_ProcessHugeMethods);8570}8571}8572}85738574uint64_t proposedScratchMemoryLimit = static_cast<uint64_t>(TR::Options::getScratchSpaceLimit());85758576// Finally, set JitDump specific options as the last step of options adjustments8577if (details.isJitDumpMethod() && options->getDebug())8578{8579auto jitDumpDetails = static_cast<J9::JitDumpMethodDetails&>(details);8580if (jitDumpDetails.getOptionsFromOriginalCompile() != NULL)8581{8582// We have the original `TR::Options` from the crashed compilation. The above logic which adjusts8583// various options is timing sensitive, and can be dependent on the VM state (startup vs not), which8584// can drastically change how the compilation looks (ex. is NextGenHCR enabled, is SVM to be used).8585//8586// Ideally we would just copy construct the current options from the original crashed compile, however8587// this is currently not possible. Although a copy constructor exists, it is not a good idea to use it8588// here due to a number of problems:8589//8590// 1. The non-copy constructor takes care of initializing tracing, among other things, which may have8591// not been active on the original compilation. There is currently no easy way for us to reinitialize8592// such logic.8593//8594// 2. Options can be set at any point during the compilation, and decisions to set options can be based8595// off of whether other options are set or not. This is very problematic. For example during the8596// original compilation we may have set option A at some point X during the compilation thus changing8597// the value of that option from that point onward. This means that if we were to copy construct the8598// set of options from the original compile right here for the JitDump compilation then option A8599// would yield a different value from the start of the compilation until point X.8600//8601// This should eventually be improved if the options framework is ever simplified to contain only option8602// values, not things like optimization plans, start PCs, compile thread IDs, etc.8603//8604// Because of this limitation we do our best to only copy options which are known to be timing sensitive8605// and that could change between the JitDump compilation and the original compilation. This is not a8606// silver bullet, and should be updated as we encounter more sources of non-determinism for JitDump8607// recompilation.86088609TR::Options* optionsFromOriginalCompile = jitDumpDetails.getOptionsFromOriginalCompile();86108611options->setOption(TR_UseSymbolValidationManager, optionsFromOriginalCompile->getOption(TR_UseSymbolValidationManager));8612options->setOption(TR_DisableGuardedCountingRecompilations, optionsFromOriginalCompile->getOption(TR_DisableGuardedCountingRecompilations));8613options->setOption(TR_DisableNextGenHCR, optionsFromOriginalCompile->getOption(TR_DisableNextGenHCR));8614}86158616options->setOption(TR_TraceAll);8617options->setOption(TR_EnableParanoidOptCheck);86188619// Tracing higher optimization level compilations may put us past the allocation limit and result in an8620// std::bad_alloc exception being thrown. To maximize our chances of getting a trace log we artificially8621// inflate the scratch space memory for JitDump compilations.8622proposedScratchMemoryLimit = UINT_MAX;86238624// Trace crashing optimization or the codegen depending on where we crashed8625UDATA vmState = that->_compInfo.getVMStateOfCrashedThread();8626if ((vmState & J9VMSTATE_JIT_CODEGEN) == J9VMSTATE_JIT_CODEGEN)8627{8628options->setOption(TR_TraceCG);8629options->setOption(TR_TraceRA);8630}8631else if ((vmState & J9VMSTATE_JIT_OPTIMIZER) == J9VMSTATE_JIT_OPTIMIZER)8632{8633OMR::Optimizations opt = static_cast<OMR::Optimizations>((vmState & 0xFF00) >> 8);8634if (0 < opt && opt < OMR::numOpts)8635{8636options->enableTracing(opt);8637}86388639// Enable additional tracing which are not part of standard optimizer tracing infrastructure8640switch (opt)8641{8642case OMR::Optimizations::inlining:8643case OMR::Optimizations::targetedInlining:8644case OMR::Optimizations::trivialInlining:8645{8646options->setOption(TR_DebugInliner);8647break;8648}8649default:8650break;8651}8652}8653}86548655// In JITServer, we would like to use JITClient's processor info for the compilation8656// The following code effectively replaces the cpu with client's cpu through the getProcessorDescription() that has JITServer support8657TR::Environment target = TR::Compiler->target;8658#if defined(J9VM_OPT_JITSERVER)8659if (that->_methodBeingCompiled->isOutOfProcessCompReq())8660{8661// Customize target.cpu based on the processor description fetched from the client8662OMRProcessorDesc JITClientProcessorDesc = that->getClientData()->getOrCacheVMInfo(that->_methodBeingCompiled->_stream)->_processorDescription;8663target.cpu = TR::CPU::customize(JITClientProcessorDesc);8664}8665else8666#endif /* defined(J9VM_OPT_JITSERVER) */8667{8668if (vm->needRelocatableTarget())8669{8670target = TR::Compiler->relocatableTarget;8671}8672}8673compiler = new (p->trMemory(), heapAlloc) TR::Compilation(8674that->getCompThreadId(),8675vmThread,8676vm,8677compilee,8678p->_ilGenRequest,8679*options,8680p->_dispatchRegion,8681p->trMemory(),8682p->_optimizationPlan,8683reloRuntime,8684&target);86858686#if defined(J9VM_OPT_JITSERVER)8687// JITServer TODO: put info in optPlan so that compilation constructor can do this8688if (that->_methodBeingCompiled->isRemoteCompReq())8689{8690compiler->setRemoteCompilation();8691// Create the KOT by default at the client if it's a remote compilation.8692// getOrCreateKnownObjectTable() checks if TR_DisableKnownObjectTable is set or not.8693compiler->getOrCreateKnownObjectTable();8694}8695else if (that->_methodBeingCompiled->isOutOfProcessCompReq())8696{8697compiler->setOutOfProcessCompilation();8698// Create the KOT by default at the server as long as it is not disabled at the client.8699compiler->getOrCreateKnownObjectTable();8700compiler->setClientData(that->getClientData());8701compiler->setStream(that->_methodBeingCompiled->_stream);8702auto compInfoPTRemote = static_cast<TR::CompilationInfoPerThreadRemote *>(that);8703compiler->setAOTCacheStore(compInfoPTRemote->isAOTCacheStore());8704}8705#endif /* defined(J9VM_OPT_JITSERVER) */87068707p->trMemory()->setCompilation(compiler);8708that->setCompilation(compiler);87098710TR_ASSERT(TR::comp() == compiler, "the TLS TR::Compilation object %p for this thread does not match the one %p just created.", TR::comp(), compiler);87118712#ifdef MCT_DEBUG8713fprintf(stderr, "Created new compiler %p ID=%d\n", compiler, compiler->getCompThreadID());8714#endif8715if (compiler)8716{8717bool isJSR292 = TR::CompilationInfo::isJSR292(details.getMethod());87188719// Check if the method to be compiled is a JSR292 method8720if (isJSR292)8721{8722/* Set options */8723compiler->getOptions()->setOption(TR_Server);8724compiler->getOptions()->setOption(TR_ProcessHugeMethods);87258726// Try to increase scratch space limit for JSR292 compilations8727proposedScratchMemoryLimit *= TR::Options::getScratchSpaceFactorWhenJSR292Workload();87288729#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)8730// Allow larger methods to be inlined into scorching bodies for JSR292 methods.8731//8732compiler->getOptions()->setBigCalleeScorchingOptThreshold(1024);8733#endif8734}8735// Under -Xtune:throughput, increase the scratch space limit for hot/scorching compilations8736else if (TR::Options::getAggressivityLevel() == TR::Options::TR_AggresivenessLevel::AGGRESSIVE_THROUGHPUT &&8737compiler->getOptions()->getOptLevel() > warm &&8738TR::Options::getScratchSpaceLimitForHotCompilations() > proposedScratchMemoryLimit) // Make sure we don't decrease the value proposed so far8739{8740proposedScratchMemoryLimit = TR::Options::getScratchSpaceLimitForHotCompilations();8741}8742#if defined(J9VM_OPT_JITSERVER)8743else if (compiler->isOutOfProcessCompilation())8744{8745// We want to increase the scratch memory if it's a out of process compilation8746proposedScratchMemoryLimit *= TR::Options::getScratchSpaceFactorWhenJITServerWorkload();8747// However, this new limit must not be larger than the half the free physical memory87488749}8750#endif87518752// Check if the method to be compiled is a Thunk Archetype8753if (details.isMethodHandleThunk())8754{8755compiler->getOptions()->setAllowRecompilation(false);8756options->setOption(TR_DisableOSR);8757options->setOption(TR_EnableOSR, false);8758}87598760// Disable recompilation for sync compiles in FSD mode. An app thread that blocks8761// on compilation releases VM Access. If class redefinition occurs during a8762// recompilation, the application thread can no longer OSR out to the interpreter;8763// it is forced to return to the oldStartPC (to jump to a helper) which may not8764// necessarily be valid.8765if (compiler->getOption(TR_FullSpeedDebug) && !that->_compInfo.asynchronousCompilation())8766{8767compiler->getOptions()->setAllowRecompilation(false);8768}87698770// Check to see if there is sufficient physical memory available for this compilation8771if (compiler->getOption(TR_EnableSelfTuningScratchMemoryUsageBeforeCompile))8772{8773bool incompleteInfo = false;8774// Abort the compile if we don't have at least getScratchSpaceLowerBound()8775// available, plus some safe reserve8776// TODO: we may want to use a lower value for third parameter below if the8777// compilation is deemed cheap (JNI, thunks, cold small method)8778uint64_t physicalLimit = that->_compInfo.computeFreePhysicalLimitAndAbortCompilationIfLow(compiler,8779incompleteInfo,8780TR::Options::getScratchSpaceLowerBound());8781// If we were able to get the memory information8782if (physicalLimit != OMRPORT_MEMINFO_NOT_AVAILABLE)8783{8784// If the proposed scratch space limit is greater than the available8785// physical memory, we need to lower the scratch space limit.8786#if defined(J9VM_OPT_JITSERVER)8787// Moreover, for JITServer do not allow a single compilation to consume8788// more than half of the free physical memory8789if (compiler->isOutOfProcessCompilation())8790physicalLimit = std::max(physicalLimit >> 1, static_cast<uint64_t>(TR::Options::getScratchSpaceLowerBound()));8791#endif8792if (proposedScratchMemoryLimit > physicalLimit)8793{8794if (incompleteInfo)8795{8796// If we weren't able to get all the memory information8797// only lower the limit for JSR292 compilations,8798// but not beyond the default value for scratch memory8799if (isJSR292)8800{8801proposedScratchMemoryLimit = (physicalLimit >= scratchSegmentProvider.allocationLimit()8802? physicalLimit8803: scratchSegmentProvider.allocationLimit());8804}8805}8806else // We have complete memory information8807{8808proposedScratchMemoryLimit = physicalLimit;8809}8810}8811}8812}88138814// Cap the limit for JIT to 4GB8815size_t proposedCapped = proposedScratchMemoryLimit > UINT_MAX ? UINT_MAX : (size_t)proposedScratchMemoryLimit;8816scratchSegmentProvider.setAllocationLimit(proposedCapped);8817}88188819if (debug("traceInfo") && optionSetIndex > 0)8820{8821if (compiler->getOutFile() != NULL)8822diagnostic("Forced Option Set %d\n", optionSetIndex);8823}8824}8825}8826catch (const std::exception &e)8827{8828// TODO: we must handle OOM cases when we abort the compilation right from the start.8829// Or eliminate the code that throws (or the code could also look at how the expensive the compilation is)8830try8831{8832throw;8833}8834#if defined(J9VM_OPT_JITSERVER)8835catch (const JITServer::StreamFailure &e)8836{8837if (TR::Options::getVerboseOption(TR_VerboseJITServer))8838TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "<EARLY TRANSLATION FAILURE: JITServer stream failure>");8839that->_methodBeingCompiled->_compErrCode = compilationStreamFailure;8840Trc_JITServerStreamFailure(vmThread, that->getCompThreadId(), __FUNCTION__, "", "", e.what());8841}8842catch (const JITServer::StreamInterrupted &e)8843{8844if (TR::Options::getVerboseOption(TR_VerboseJITServer))8845TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "<EARLY TRANSLATION FAILURE: compilation interrupted by JITClient>");8846that->_methodBeingCompiled->_compErrCode = compilationStreamInterrupted;8847Trc_JITServerStreamInterrupted(vmThread, that->getCompThreadId(), __FUNCTION__, "", "", e.what());8848}8849#endif /* defined(J9VM_OPT_JITSERVER) */8850catch (const J9::JITShutdown)8851{8852if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))8853TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: JIT Shutdown signaled>");8854that->_methodBeingCompiled->_compErrCode = compilationFailure;8855}8856catch (const std::bad_alloc &e)8857{8858if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))8859TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: out of scratch memory>");8860that->_methodBeingCompiled->_compErrCode = compilationFailure;8861Trc_JIT_outOfMemory(vmThread);8862}8863catch (const std::exception &e)8864{8865if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))8866TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: compilation aborted>");8867that->_methodBeingCompiled->_compErrCode = compilationFailure;8868}88698870if (compiler)8871{8872// The KOT needs to survive at least until we're done committing virtual guards and we must not be holding the8873// comp monitor prior to freeing the KOT because it requires VM access.8874if (compiler->getKnownObjectTable())8875compiler->freeKnownObjectTable();88768877compiler->~Compilation();8878}88798880compiler = NULL;8881p->trMemory()->setCompilation(NULL);8882that->setCompilation(NULL);8883}88848885TR_MethodMetaData * metaData = NULL;88868887if (compiler)8888{8889if (compiler->getRecompilationInfo())8890{8891// if the compiler is created successfully and the method supports recompilation, we can set this field on the bodyInfo8892TR_PersistentJittedBodyInfo *bodyInfo = compiler->getRecompilationInfo()->getJittedBodyInfo();8893if (bodyInfo)8894{8895bodyInfo->setStartPCAfterPreviousCompile(that->_methodBeingCompiled->_oldStartPC);8896if (reducedWarm && options->getOptLevel() == warm)8897bodyInfo->setReducedWarm();8898}8899}89008901const char *hotnessString = compiler->getHotnessName(compiler->getMethodHotness());89028903Trc_JIT_compileStart(vmThread, hotnessString, compiler->signature());89048905TR_ASSERT(compiler->getMethodHotness() != unknownHotness, "Trying to compile at unknown hotness level");89068907metaData = that->compile(vmThread, compiler, compilee, *vm, p->_optimizationPlan, scratchSegmentProvider);89088909}89108911try8912{8913// Store hints in the SCC8914TR_J9SharedCache *sc = (TR_J9SharedCache *) (vm->sharedCache());8915if (metaData && !that->_methodBeingCompiled->isDLTCompile() &&8916!that->_methodBeingCompiled->isAotLoad() && sc) // skip AOT loads8917{8918J9Method *method = that->_methodBeingCompiled->getMethodDetails().getMethod();8919TR_J9VMBase *fej9 = (TR_J9VMBase *)(compiler->fej9());8920if (!fej9->isAOT_DEPRECATED_DO_NOT_USE())8921{8922bool isEDOCompilation = false;8923TR_CatchBlockProfileInfo * profileInfo = TR_CatchBlockProfileInfo::get(compiler);8924if (profileInfo && profileInfo->getCatchCounter() >= TR_CatchBlockProfileInfo::EDOThreshold)8925{8926isEDOCompilation = true;8927sc->addHint(method, TR_HintEDO);8928}89298930// There is the possibility that a hot/scorching compilation happened outside8931// startup and with hints we move this expensive compilation during startup8932// thus affecting startup time8933// To minimize risk, add hot/scorching hints only if we are in startup mode8934if (TR::Compiler->vm.isVMInStartupPhase(jitConfig))8935{8936TR_Hotness hotness = that->_methodBeingCompiled->_optimizationPlan->getOptLevel();8937if (hotness == hot)8938{8939if (!isEDOCompilation)8940sc->addHint(method, TR_HintHot);8941}8942else if (hotness == scorching)8943{8944sc->addHint(method, TR_HintScorching);8945}8946// We also want to add a hint about methods compiled (not AOTed) during startup8947// In subsequent runs we should give such method lower counts the idea being8948// that if I take the time to compile method, why not do it sooner8949sc->addHint(method, TR_HintMethodCompiledDuringStartup);8950}8951}89528953// If this is a cold/warm compilation that takes too much memory8954// add a hint to avoid queuing a forced upgrade8955// Look only during startup to avoid creating too many hints.8956// If SCC is larger we could store hints for more methods8957//8958if (TR::Compiler->vm.isVMInStartupPhase(jitConfig))8959{8960if (scratchSegmentProvider.regionBytesAllocated() > TR::Options::_memExpensiveCompThreshold)8961{8962TR_Hotness hotness = that->_methodBeingCompiled->_optimizationPlan->getOptLevel();8963if (hotness <= cold)8964{8965sc->addHint(method, TR_HintLargeMemoryMethodC);8966}8967else if (hotness == warm)8968{8969sc->addHint(method, TR_HintLargeMemoryMethodW);8970}8971}89728973if (that->getCompilationInfo()->getMethodQueueSize() - that->getQszWhenCompStarted() > TR::Options::_cpuExpensiveCompThreshold)8974{8975TR_Hotness hotness = that->_methodBeingCompiled->_optimizationPlan->getOptLevel();8976if (hotness <= cold)8977{8978sc->addHint(method, TR_HintLargeCompCPUC);8979}8980else if (hotness == warm)8981{8982sc->addHint(method, TR_HintLargeCompCPUW);8983}8984}8985}8986}8987}8988#if defined(J9VM_OPT_JITSERVER)8989catch (const JITServer::StreamFailure &e)8990{8991// Stream failure here means it was produced by one of the calls to sc->addHint8992// Fail the compilation here since attempting to finish it will result8993// in another StreamFailure8994that->_methodBeingCompiled->_compErrCode = compilationStreamFailure;8995metaData = NULL; // indicate that the compilation has failed for postCompilationTasks8996if (TR::Options::getVerboseOption(TR_VerboseJITServer))8997TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamFailure: %s", that->getCompThreadId(), e.what());8998Trc_JITServerStreamFailure(vmThread, that->getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());8999}9000#endif /* defined(J9VM_OPT_JITSERVER) */9001catch (const std::exception &e)9002{9003// Catch-all case to handle any potential failures not related to JITServer9004// At this point we have compiled method successfuly but failed to add hints.9005// We will ignore this exception and continue hoping that compilation can be finished.9006}9007return metaData;9008}90099010static bool9011foundJ9SharedDataForMethod(TR_OpaqueMethodBlock *method, TR::Compilation *comp, J9JITConfig *jitConfig)9012{9013unsigned char buffer[1000];9014uint32_t length = 1000;9015J9SharedDataDescriptor descriptor;9016if (!TR::Options::sharedClassCache())9017return false;9018J9SharedClassConfig * scConfig = jitConfig->javaVM->sharedClassConfig;9019descriptor.address = buffer;9020descriptor.length = length;9021descriptor.type = J9SHR_ATTACHED_DATA_TYPE_JITPROFILE;9022descriptor.flags = J9SHR_ATTACHED_DATA_NO_FLAGS;9023J9VMThread *vmThread = ((TR_J9VM *)comp->fej9())->getCurrentVMThread();9024J9ROMMethod * romMethod = comp->fej9()->getROMMethodFromRAMMethod((J9Method *)method);9025IDATA dataIsCorrupt;9026void *store = (void *)scConfig->findAttachedData(vmThread, romMethod, &descriptor, &dataIsCorrupt);9027if (store != (void *)descriptor.address) // a stronger check, as found can be error value9028return false;9029return store ? true : false;9030}90319032// Helper function to perform AOT Load process9033TR_MethodMetaData *9034TR::CompilationInfoPerThreadBase::performAOTLoad(9035J9VMThread * vmThread,9036TR::Compilation * compiler,9037TR_ResolvedMethod * compilee,9038TR_J9VMBase *vm,9039J9Method * method9040)9041{9042TR_FilterBST *filterInfo = NULL;9043TR_ASSERT(methodCanBeCompiled(compiler->trMemory(), vm, compilee, filterInfo), "This should already have failed in wrappedCompile");90449045// Perform an AOT load9046//9047// Load the AOT body using a non shared cache VM (don't use vm because it's J9SharedCacheVM for the compile)9048TR_J9VMBase *loadvm = TR_J9VMBase::get(jitConfig, vmThread);9049if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9050{9051TR_VerboseLog::writeLineLocked(9052TR_Vlog_DISPATCH,9053"Loading previously AOT compiled body for %s @ %s",9054compiler->signature(),9055compiler->getHotnessName()9056);9057}90589059#if defined(OSX) && defined(AARCH64)9060pthread_jit_write_protect_np(0);9061#endif9062TR_MethodMetaData *metaData = installAotCachedMethod(9063vmThread,9064_methodBeingCompiled->_aotCodeToBeRelocated,9065method,9066loadvm,9067compiler->getOptions(),9068compilee,9069_methodBeingCompiled,9070compiler9071);9072#if defined(OSX) && defined(AARCH64)9073pthread_jit_write_protect_np(1);9074#endif90759076_methodBeingCompiled->_newStartPC = metaData ? reinterpret_cast<void *>(metaData->startPC) : 0;90779078if (!metaData) // Failed to relocate!9079{9080if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9081{9082TR_VerboseLog::writeLineLocked(9083TR_Vlog_DISPATCH,9084"Failed to load previously AOT compiled body for %s @ %s",9085compiler->signature(),9086compiler->getHotnessName()9087);9088}90899090compiler->failCompilation<J9::AOTRelocationFailed>("Failed to relocate");9091}9092else9093{9094if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9095{9096TR_VerboseLog::writeLineLocked(9097TR_Vlog_DISPATCH,9098"Successfully loaded previously AOT compiled body for %s @ %s",9099compiler->signature(),9100compiler->getHotnessName()9101);9102}9103// if we delayed relocation, persist iprofiler info here9104if (!compiler->getOption(TR_DisableDelayRelocationForAOTCompilations))9105{9106TR_SharedCache *sc = compiler->fej9()->sharedCache();9107if (sc && !foundJ9SharedDataForMethod(compilee->getPersistentIdentifier(), compiler, _jitConfig))9108{9109sc->persistIprofileInfo(NULL, compilee, compiler);9110TR_MethodMetaData *metaData = _methodBeingCompiled->_compInfoPT->getMetadata();9111U_32 numCallSites = getNumInlinedCallSites(metaData);9112TR::StackMemoryRegion stackMemoryRegion(*compiler->trMemory());9113for (int32_t i = 0; i < numCallSites; i++)9114{9115U_8 * inlinedCallSite = getInlinedCallSiteArrayElement(metaData, i);9116TR_OpaqueMethodBlock* j9method = (TR_OpaqueMethodBlock *)getInlinedMethod(inlinedCallSite);9117if(!isPatchedValue((J9Method *)j9method))9118{9119TR_ResolvedJ9Method resolvedj9method = TR_ResolvedJ9Method(j9method, compiler->fej9(), compiler->trMemory());9120TR_ResolvedMethod *method = &resolvedj9method;9121sc->persistIprofileInfo(NULL, method, compiler);9122}9123}9124}9125}9126}9127return metaData;9128}91299130// This routine should only be called from wrappedCompile9131TR_MethodMetaData *9132TR::CompilationInfoPerThreadBase::compile(9133J9VMThread * vmThread,9134TR::Compilation * compiler,9135TR_ResolvedMethod * compilee,9136TR_J9VMBase &vm,9137TR_OptimizationPlan *optimizationPlan,9138TR::SegmentAllocator const &scratchSegmentProvider9139)9140{91419142PORT_ACCESS_FROM_JAVAVM(_jitConfig->javaVM);9143J9JavaVM *javaVM = _jitConfig->javaVM;91449145TR_MethodMetaData * metaData = NULL;91469147if (_methodBeingCompiled->_priority >= CP_SYNC_MIN)9148++_compInfo._numSyncCompilations;9149else9150++_compInfo._numAsyncCompilations;91519152if (_methodBeingCompiled->isDLTCompile())9153compiler->setDltBcIndex(static_cast<J9::MethodInProgressDetails &>(_methodBeingCompiled->getMethodDetails()).getByteCodeIndex());91549155bool volatile haveLockedClassUnloadMonitor = false; // used for compilation without VM access91569157try9158{9159InterruptibleOperation compilingMethodBody(*this);91609161TR::IlGeneratorMethodDetails & details = _methodBeingCompiled->getMethodDetails();9162J9Method *method = details.getMethod();91639164TRIGGER_J9HOOK_JIT_COMPILING_START(_jitConfig->hookInterface, vmThread, method);91659166// Prepare compilation9167//9168if (_jitConfig->tracingHook)9169compiler->setDebug(9170((TR_CreateDebug_t)_jitConfig->tracingHook)(compiler)9171);9172if (!_methodBeingCompiled->isRemoteCompReq()) // remote compilations are performed elsewhere9173{9174// Print compiling method9175//9176struct CompilationTrace9177{9178CompilationTrace(TR::Compilation &compiler) : _compiler(compiler)9179{9180TR_ASSERT(_compiler.getHotnessName(_compiler.getMethodHotness()), "expected to have a hotness string");9181if (_compiler.getOutFile() != NULL && _compiler.getOption(TR_TraceAll))9182{9183traceMsg(&_compiler, "<compile\n");9184traceMsg(&_compiler, "\tmethod=\"%s\"\n", _compiler.signature());9185traceMsg(&_compiler, "\thotness=\"%s\"\n", _compiler.getHotnessName(_compiler.getMethodHotness()));9186traceMsg(&_compiler, "\tisProfilingCompile=%d", _compiler.isProfilingCompilation());9187#if defined(J9VM_OPT_JITSERVER)9188if (_compiler.isOutOfProcessCompilation() && TR::compInfoPT->getClientData()) // using jitserver && client JVM9189{9190traceMsg(&_compiler, "\n");9191traceMsg(&_compiler, "\tclientID=%" OMR_PRIu64, TR::compInfoPT->getClientData()->getClientUID());9192}9193#endif /* defined(J9VM_OPT_JITSERVER) */9194traceMsg(&_compiler, ">\n");9195}9196}9197~CompilationTrace() throw()9198{9199if (_compiler.getOutFile() != NULL && _compiler.getOption(TR_TraceAll))9200traceMsg(&_compiler, "</compile>\n\n");9201}9202private:9203TR::Compilation &_compiler;9204};9205CompilationTrace compilationTrace(*compiler);9206}92079208if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileStart))9209{9210char compilationTypeString[15]={0};9211TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",9212vm.isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",9213compiler->isProfilingCompilation() ? "profiled " : ""9214);9215bool incomplete;9216uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incomplete);92179218if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE)9219{9220TR_VerboseLog::writeLineLocked(9221TR_Vlog_COMPSTART,9222"(%s%s) Compiling %s %s %s j9m=%p %s t=%llu compThreadID=%d memLimit=%zu KB freePhysicalMemory=%llu MB",9223compilationTypeString,9224compiler->getHotnessName(compiler->getMethodHotness()),9225compiler->signature(),9226compiler->isDLT() ? "DLT" : "",9227details.name(),9228method,9229_methodBeingCompiled->isRemoteCompReq() ? "remote" : "",9230_compInfo.getPersistentInfo()->getElapsedTime(),9231compiler->getCompThreadID(),9232scratchSegmentProvider.allocationLimit() >> 10,9233freePhysicalMemorySizeB >> 209234);9235}9236else9237{9238TR_VerboseLog::writeLineLocked(9239TR_Vlog_COMPSTART,9240"(%s%s) Compiling %s %s %s j9m=%p t=%llu compThreadID=%d memLimit=%zu KB",9241compilationTypeString,9242compiler->getHotnessName(compiler->getMethodHotness()),9243compiler->signature(),9244compiler->isDLT() ? "DLT" : "",9245details.name(),9246method,9247_compInfo.getPersistentInfo()->getElapsedTime(),9248compiler->getCompThreadID(),9249scratchSegmentProvider.allocationLimit() >> 109250);9251}9252}92539254// Precompile option appears in HRT documentation9255//9256if (TR::Options::getVerboseOption(TR_VerbosePrecompile))9257{9258TR_VerboseLog::writeLineLocked(TR_Vlog_PRECOMP,"%s", compiler->signature());9259}92609261if (9262_methodBeingCompiled->_oldStartPC9263&& compiler->getOption(TR_FailPreXRecompile)9264&& TR::Recompilation::getJittedBodyInfoFromPC(_methodBeingCompiled->_oldStartPC)->getIsInvalidated()9265)9266{9267compiler->failCompilation<TR::CompilationException>("TR_FailPreXRecompile option");9268}92699270// If we want to compile without VM access, now it's the time to release it9271// For the JITClient we must not enter this path. The class unload monitor9272// will not be acquired/released and we'll only release VMaccess when9273// waiting for a reply from the server9274if (!compiler->getOption(TR_DisableNoVMAccess) &&9275!_methodBeingCompiled->_aotCodeToBeRelocated &&9276!_methodBeingCompiled->isRemoteCompReq())9277{9278#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)9279bool doAcquireClassUnloadMonitor = true;9280#else9281bool doAcquireClassUnloadMonitor = compiler->getOption(TR_EnableHCR) || compiler->getOption(TR_FullSpeedDebug);9282#endif9283if (doAcquireClassUnloadMonitor)9284{9285_compInfo.debugPrint(NULL, "\tcompilation thread acquiring class unload monitor\n");9286TR::MonitorTable::get()->readAcquireClassUnloadMonitor(getCompThreadId());9287haveLockedClassUnloadMonitor = true;9288}9289releaseVMAccess(vmThread);9290// GC can go ahead now.9291}92929293// The inlineFieldWatches flag is set when Field Watch is actually triggered at runtime.9294// When it happens, all the methods on stack are decompiled and those in9295// the compilation queue are invalidated. Set the option here to guarantee the9296// mode is detected at the right moment so that all methods compiled after respect the9297// data watch point.9298//9299if (_jitConfig->inlineFieldWatches)9300compiler->setOption(TR_EnableFieldWatch);93019302// Compile the method9303//93049305// For local AOT and JITServer we need to reserve a data cache to ensure contiguous memory9306// For TOSS_CODE we need to reserve a data cache so that we know what dataCache9307// to reset when throwing the data away9308//9309if ((_jitConfig->runtimeFlags & J9JIT_TOSS_CODE)9310|| _methodBeingCompiled->isOutOfProcessCompReq()9311#if defined(J9VM_INTERP_AOT_COMPILE_SUPPORT)9312|| (vm.isAOT_DEPRECATED_DO_NOT_USE() && !_methodBeingCompiled->isRemoteCompReq())9313#endif //endif J9VM_INTERP_AOT_COMPILE_SUPPORT9314)9315{9316// Need to reserve a data cache9317// if this is a retrial we may already have a data cache that is reserved9318// by the previous compilation; check this scenario first9319//9320if (_reservedDataCache)9321{9322TR_ASSERT(_methodBeingCompiled->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS, "reserved dataCache for a brand new compilation\n");9323compiler->setReservedDataCache(_reservedDataCache);9324_reservedDataCache = NULL; // we don't need this field anymore; It is only used to pass9325// the information about reserved data caches from one retrial9326// to the next9327}9328else9329{9330// TODO: find an appropriate datacache size9331TR_DataCache *dataCache = TR_DataCacheManager::getManager()->reserveAvailableDataCache(vmThread, 4*1024);9332compiler->setReservedDataCache(dataCache);9333if (!dataCache)9334{9335compiler->failCompilation<J9::DataCacheError>("Cannot reserve dataCache");9336}9337}93389339TR_DataCache *dataCache = (TR_DataCache*)compiler->getReservedDataCache();9340dataCache->setAllocationMark();9341}9342else // non AOT, non TOSS_CODE9343{9344// Safety net; cancel the reservations from previous compilations9345if (_reservedDataCache)9346{9347TR_ASSERT(_methodBeingCompiled->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS, "Reserved dcache must be saved only for a comp retrial");9348TR_DataCacheManager::getManager()->makeDataCacheAvailable(_reservedDataCache);9349_reservedDataCache = NULL;9350}9351}93529353if ((vm.isAOT_DEPRECATED_DO_NOT_USE() && !_methodBeingCompiled->isRemoteCompReq()) || _methodBeingCompiled->isOutOfProcessCompReq())9354{9355TR_DataCache *dataCache = (TR_DataCache*)compiler->getReservedDataCache();9356TR_ASSERT(dataCache, "Must have a reserved dataCache for AOT compilations");9357compiler->setAotMethodDataStart((uint32_t *)dataCache->getCurrentHeapAlloc());93589359// First allocate a TR_AOTMethodHeader9360//9361TR_AOTMethodHeader *cacheEntryAOTMethodHeader = pointer_cast<TR_AOTMethodHeader *>(vm.allocateRelocationData(compiler, sizeof(struct TR_AOTMethodHeader)));9362TR_ASSERT(cacheEntryAOTMethodHeader, "Must have cacheEntryAOTMethodHeader or throw an exception");9363memset(cacheEntryAOTMethodHeader, 0, sizeof(struct TR_AOTMethodHeader));9364// Go back to find the J9JITDataCacheHeader9365J9JITDataCacheHeader *cacheEntry = pointer_cast<J9JITDataCacheHeader *>(cacheEntryAOTMethodHeader) - 1;93669367// the size is set up by allocateRelocationData which also does the rounding;9368cacheEntry->type = J9_JIT_DCE_AOT_METHOD_HEADER;9369compiler->setAotMethodDataStart(cacheEntry);9370cacheEntryAOTMethodHeader->majorVersion = TR_AOTMethodHeader_MajorVersion; // AOT code and data major version9371cacheEntryAOTMethodHeader->minorVersion = TR_AOTMethodHeader_MinorVersion; // AOT code and data minor version9372}93739374intptr_t rtn = 0;93759376if (_methodBeingCompiled->isAotLoad())9377{9378metaData = performAOTLoad(vmThread, compiler, compilee, &vm, method);9379}9380#if defined(J9VM_OPT_JITSERVER)9381else if (_methodBeingCompiled->isRemoteCompReq()) // JITServer Client Mode9382{9383metaData = remoteCompile(vmThread, compiler, compilee, method, details, this);9384}9385#endif /* defined(J9VM_OPT_JITSERVER) */9386else // non-jitserver, non-aot-load9387{9388if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9389{9390TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "Compiling %s @ %s", compiler->signature(), compiler->getHotnessName());9391}93929393if (compiler->getOption(TR_AlwaysSafeFatal))9394{9395TR_ASSERT_SAFE_FATAL(false, "alwaysSafeFatal set");9396TR_VerboseLog::writeLineLocked(9397TR_Vlog_INFO,9398"Bypassed TR_ASSERT_SAFE_FATAL %s @ %s",9399compiler->signature(),9400compiler->getHotnessName()9401);9402}94039404if (compiler->getOption(TR_AlwaysFatalAssert))9405{9406TR_ASSERT_FATAL(false, "alwaysFatalAssert set");9407}94089409if (vm.isAOT_DEPRECATED_DO_NOT_USE() &&9410compiler->getOption(TR_UseSymbolValidationManager))9411compiler->getSymbolValidationManager()->populateWellKnownClasses();94129413rtn = compiler->compile();94149415if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch) && !rtn)9416{9417TR_VerboseLog::writeLineLocked(9418TR_Vlog_DISPATCH,9419"Successfully created compiled body [" POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT "] for %s @ %s",9420compiler->cg()->getCodeStart(),9421compiler->cg()->getCodeEnd(),9422compiler->signature(),9423compiler->getHotnessName());9424}9425}94269427// Re-acquire VM access if needed9428//9429if (!compiler->getOption(TR_DisableNoVMAccess))9430{9431#if !defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)9432if (compiler->getOption(TR_EnableHCR) || compiler->getOption(TR_FullSpeedDebug))9433#endif9434{9435if (haveLockedClassUnloadMonitor)9436{9437TR::MonitorTable::get()->readReleaseClassUnloadMonitor(getCompThreadId());9438haveLockedClassUnloadMonitor = false; // Need this because an exception might happen during createMethodMetadata9439} // and on the exception path we check haveLockedClassUnloadMonitor9440// Here the GC/HCR might happen9441}9442if (!_methodBeingCompiled->isRemoteCompReq() && !(vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS))9443acquireVMAccessNoSuspend(vmThread);94449445// The GC could have unloaded some classes when we released the classUnloadMonitor, or HCR could have kicked in9446//9447if (compilationShouldBeInterrupted())9448{9449if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9450{9451TR_VerboseLog::writeLineLocked(9452TR_Vlog_DISPATCH,9453"Interrupting compilation of %s @ %s",9454compiler->signature(),9455compiler->getHotnessName()9456);9457}9458compiler->failCompilation<TR::CompilationInterrupted>("Compilation interrupted");9459}9460}94619462if (rtn != COMPILATION_SUCCEEDED)9463{9464TR_ASSERT(false, "Compiler returned non zero return code %d\n", rtn);9465compiler->failCompilation<TR::CompilationException>("Compilation Failure");9466}94679468if (TR::Options::getVerboseOption(TR_VerboseCompYieldStats))9469{9470if (compiler->getMaxYieldInterval() > TR::Options::_compYieldStatsThreshold)9471{9472TR_VerboseLog::CriticalSection vlogLock;9473compiler->printCompYieldStats();9474}9475}94769477_methodBeingCompiled->_compErrCode = compilationOK;9478if (!_methodBeingCompiled->isAotLoad()9479#if defined(J9VM_OPT_JITSERVER)9480&& !_methodBeingCompiled->isRemoteCompReq()9481#endif /* defined(J9VM_OPT_JITSERVER) */9482)9483{9484class TraceMethodMetadata9485{9486public:9487TraceMethodMetadata(TR::Compilation &compiler) :9488_compiler(compiler),9489_trace(compiler.getOutFile() != NULL && compiler.getOption(TR_TraceAll))9490{9491if (_trace)9492traceMsg(&_compiler, "<metadata>\n");9493}9494~TraceMethodMetadata()9495{9496if (_trace)9497traceMsg(&_compiler, "</metadata>\n");9498}9499private:9500TR::Compilation &_compiler;9501const bool _trace;9502};95039504TraceMethodMetadata traceMetadata(*compiler);95059506if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9507{9508TR_VerboseLog::writeLineLocked(9509TR_Vlog_DISPATCH,9510"Creating metadata for %s @ %s",9511compiler->signature(),9512compiler->getHotnessName()9513);9514}95159516metaData = createMethodMetaData(vm, compilee, compiler);9517if (!metaData)9518{9519if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9520{9521TR_VerboseLog::writeLineLocked(9522TR_Vlog_DISPATCH,9523"Failed to create metadata for %s @ %s",9524compiler->signature(),9525compiler->getHotnessName()9526);9527}9528compiler->failCompilation<J9::MetaDataCreationFailure>("Metadata creation failure");9529}95309531if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9532{9533TR_VerboseLog::writeLineLocked(9534TR_Vlog_DISPATCH,9535"Successfully created metadata [" POINTER_PRINTF_FORMAT "] for %s @ %s",9536metaData,9537compiler->signature(),9538compiler->getHotnessName()9539);9540}954195429543#if defined(OSX) && defined(AARCH64)9544pthread_jit_write_protect_np(0);9545#endif9546// Put a metaData pointer into the Code Cache Header(s).9547//9548uint8_t *warmMethodHeader = compiler->cg()->getBinaryBufferStart() - sizeof(OMR::CodeCacheMethodHeader);9549memcpy( warmMethodHeader + offsetof(OMR::CodeCacheMethodHeader, _metaData), &metaData, sizeof(metaData) );9550if ( metaData->startColdPC )9551{9552uint8_t *coldMethodHeader = reinterpret_cast<uint8_t *>(metaData->startColdPC) - sizeof(OMR::CodeCacheMethodHeader);9553memcpy( coldMethodHeader + offsetof(OMR::CodeCacheMethodHeader, _metaData), &metaData, sizeof(metaData) );9554}95559556// FAR: should we do postpone this copying until after CHTable commit?9557metaData->runtimeAssumptionList = *(compiler->getMetadataAssumptionList());95589559// We don't need to delete the metadataAssumptionList from the compilation object,9560// and in fact it would be wrong to do so because code during chtable.commit is9561// expecting something in the compiler object9562}9563#if defined(OSX) && defined(AARCH64)9564pthread_jit_write_protect_np(1);9565#endif95669567setMetadata(metaData);95689569if (compiler->getOption(TR_BreakAfterCompile))9570{9571fprintf(stderr, "\n=== Finished compiling %s at %p ===\n", compiler->signature(), (void *)metaData->startPC);9572TR::Compiler->debug.breakPoint();9573}95749575if (metaData &&9576compiler->getPersistentInfo()->isRuntimeInstrumentationEnabled())9577{9578// This must be called after createMethodMetaData because TR_PersistentJittedBodyInfo can change in that function.9579_compInfo.getHWProfiler()->registerRecords(metaData, compiler);9580}95819582TR_CHTable *chTable = compiler->getCHTable();9583if (chTable && !chTable->canSkipCommit(compiler))9584{9585TR::ClassTableCriticalSection chTableCommit(&vm);9586TR_ASSERT(!chTableCommit.acquiredVMAccess(), "We should have already acquired VM access at this point.");9587if (chTable->commit(compiler) == false)9588{9589// If we created a TR_PersistentMethodInfo, fix the next compilation level9590// because if we retry the compilation we will fail an assume later on9591// due to discrepancy in compilation level.9592if (metaData->startPC)9593{9594TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(reinterpret_cast<void *>(metaData->startPC));9595if (bodyInfo)9596{9597bodyInfo->getMethodInfo()->setNextCompileLevel(bodyInfo->getHotness(), false);9598}9599}96009601if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance, TR_VerboseCompFailure))9602{9603TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, "Failure while committing chtable for %s", compiler->signature());9604}96059606if (!compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE())9607{9608TR_J9SharedCache *sc = (TR_J9SharedCache *) (compiler->fej9()->sharedCache());9609if (sc)9610sc->addHint(compiler->getCurrentMethod(), TR_HintFailedCHTable);9611}9612compiler->failCompilation<J9::CHTableCommitFailure>("CHTable commit failure");9613}9614}96159616// As the body is finished, mark its profile info as active so that the JProfiler thread will inspect it9617if (compiler->getRecompilationInfo())9618{9619TR_PersistentJittedBodyInfo *bodyInfo = compiler->getRecompilationInfo()->getJittedBodyInfo();9620if (bodyInfo && bodyInfo->getProfileInfo())9621{9622bodyInfo->getProfileInfo()->setActive();9623}9624}96259626logCompilationSuccess(vmThread, vm, method, scratchSegmentProvider, compilee, compiler, metaData, optimizationPlan);96279628TRIGGER_J9HOOK_JIT_COMPILING_END(_jitConfig->hookInterface, vmThread, method);9629}9630catch (const std::exception &e)9631{9632const char *exceptionName;96339634#if defined(J9ZOS390)9635// Compiling with -Wc,lp64 results in a crash on z/OS when trying9636// to call the what() virtual method of the exception.9637exceptionName = "std::exception";9638#else9639exceptionName = e.what();9640#endif96419642printCompFailureInfo(compiler, exceptionName);9643processException(vmThread, scratchSegmentProvider, compiler, haveLockedClassUnloadMonitor, exceptionName);9644metaData = 0;9645}96469647// At this point the compilation has either succeeded and compilation cannot be9648// interrupted anymore, or it has failed. In either case _compilationShouldBeinterrupted flag9649// is not needed anymore9650setCompilationShouldBeInterrupted(0);96519652// We should not have the classTableMutex at this point9653TR_ASSERT_FATAL(!TR::MonitorTable::get()->getClassTableMutex()->owned_by_self(),9654"Should not still own classTableMutex");96559656// Increment the number of JIT compilations (either successful or not)9657// performed by this compilation thread9658//9659incNumJITCompilations();96609661return metaData;9662}96639664#if defined(JIT_METHODHANDLE_TRANSLATED)9665// TODO: Remove this once the VM supplies this declaration9666extern J9_CFUNC void jitMethodHandleTranslated (J9VMThread *currentThread, j9object_t methodHandle, j9object_t arg, void *jitEntryPoint, void *intrpEntryPoint);9667#endif966896699670// static method9671void *9672TR::CompilationInfo::compilationEnd(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details, J9JITConfig *jitConfig, void *startPC,9673void *oldStartPC, TR_FrontEnd *fe, TR_MethodToBeCompiled *entry, TR::Compilation *comp)9674{9675// This method is only called with both VMAccess and CompilationMutex in hand.9676// Performs some necessary updates once a compilation has been attempted9677//9678PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);9679TR_DataCache *dataCache = NULL;9680TR::CompilationInfo *compInfo = TR::CompilationInfo::get();96819682bool isJITServerMode = false;9683#if defined(J9VM_OPT_JITSERVER)9684isJITServerMode = compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER;9685#endif /* defined(J9VM_OPT_JITSERVER) */96869687if (details.isNewInstanceThunk())9688{9689if (isJITServerMode)9690{9691#if defined(J9VM_OPT_JITSERVER)9692if (startPC) // compilation succeeded9693{9694outOfProcessCompilationEnd(entry, comp);9695}9696else if (entry)9697{9698if (TR::Options::getVerboseOption(TR_VerboseJITServer))9699{9700TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,9701"compThreadID=%d has failed to compile a new instance thunk", entry->_compInfoPT->getCompThreadId());9702}9703Trc_JITServerFailedToCompileNewInstanceThunk(vmThread, entry->_compInfoPT->getCompThreadId());9704int8_t compErrCode = entry->_compErrCode;9705if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)9706entry->_stream->writeError(compErrCode);9707}9708#endif /* defined(J9VM_OPT_JITSERVER) */9709}9710else9711{9712J9::NewInstanceThunkDetails &mhDetails = static_cast<J9::NewInstanceThunkDetails &>(details);9713J9Class *clazz = mhDetails.classNeedingThunk();9714if (startPC)9715jitNewInstanceMethodTranslated(vmThread, clazz, startPC);9716else9717jitNewInstanceMethodTranslateFailed(vmThread, clazz);9718}97199720if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)9721{9722if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)9723jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;97249725dataCache = (TR_DataCache*)comp->getReservedDataCache();9726if (dataCache)9727{9728dataCache->resetAllocationToMark();9729// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)9730TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);9731comp->setReservedDataCache(NULL);9732}9733}97349735return startPC;9736}97379738if (details.isMethodInProgress())9739{9740#if defined(J9VM_OPT_JITSERVER)9741if (isJITServerMode)9742{9743if (startPC) // compilation succeeded9744{9745outOfProcessCompilationEnd(entry, comp);9746}9747else if (entry) // failure9748{9749if (TR::Options::getVerboseOption(TR_VerboseJITServer))9750{9751TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,9752"compThreadID=%d has failed to compile a DLT method", entry->_compInfoPT->getCompThreadId());9753}9754Trc_JITServerFailedToCompileDLT(vmThread, entry->_compInfoPT->getCompThreadId());9755int8_t compErrCode = entry->_compErrCode;9756if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)9757entry->_stream->writeError(compErrCode);9758}9759}9760else // local compilation9761#endif /* defined(J9VM_OPT_JITSERVER) */9762{9763if (startPC) // compilation succeeded9764{9765#ifdef J9VM_JIT_DYNAMIC_LOOP_TRANSFER9766J9::MethodInProgressDetails & dltDetails = static_cast<J9::MethodInProgressDetails &>(details);9767TR::CompilationInfo *compInfo = TR::CompilationInfo::get();9768compInfo->insertDLTRecord(dltDetails.getMethod(), dltDetails.getByteCodeIndex(), startPC);9769jitMarkMethodReadyForDLT(vmThread, dltDetails.getMethod());9770#endif // ifdef J9VM_JIT_DYNAMIC_LOOP_TRANSFER9771}9772}97739774if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)9775{9776if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)9777jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;97789779dataCache = (TR_DataCache *)comp->getReservedDataCache();9780if (dataCache)9781{9782dataCache->resetAllocationToMark();9783// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)9784TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);9785comp->setReservedDataCache(NULL);9786}9787}9788return startPC;9789}97909791if (!fe)9792fe = TR_J9VMBase::get(jitConfig, vmThread);97939794TR_J9VMBase *trvm = (TR_J9VMBase *)fe;97959796if (details.isMethodHandleThunk())9797{9798#if defined(J9VM_OPT_JITSERVER)9799if (isJITServerMode)9800{9801if (startPC) // compilation succeeded9802{9803outOfProcessCompilationEnd(entry, comp);9804}9805else if (entry) // failure9806{9807if (TR::Options::getVerboseOption(TR_VerboseJITServer))9808{9809TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,9810"compThreadID=%d has failed to compile a methodHandleThunk method", entry->_compInfoPT->getCompThreadId());9811}9812Trc_JITServerFailedToCompileMethodHandleThunk(vmThread, entry->_compInfoPT->getCompThreadId());9813int8_t compErrCode = entry->_compErrCode;9814if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)9815entry->_stream->writeError(compErrCode);9816}9817}9818else // local compilation9819#endif /* defined(J9VM_OPT_JITSERVER) */9820{9821if (startPC)9822{9823J9::MethodHandleThunkDetails &mhDetails = static_cast<J9::MethodHandleThunkDetails &>(details);9824uintptr_t thunks = trvm->getReferenceField(*mhDetails.getHandleRef(), "thunks", "Ljava/lang/invoke/ThunkTuple;");9825int64_t jitEntryPoint = (int64_t)(intptr_t)startPC + J9::PrivateLinkage::LinkageInfo::get(startPC)->getJitEntryOffset();98269827#if defined(JIT_METHODHANDLE_TRANSLATED)9828jitMethodHandleTranslated(vmThread, *mhDetails.getHandleRef(), mhDetails.getArgRef() ? *mhDetails.getArgRef() : NULL, jitEntryPoint, startPC);9829#else9830// This doesn't need to be volatile. On 32-bit, we don't care about9831// word-tearing because it's a 32-bit address; on 64-bit, we don't get9832// word-tearing of aligned 64-bit stores on any platform we care about.9833//9834trvm->setInt64Field(thunks, "invokeExactThunk", jitEntryPoint);9835trvm->setInt64Field(thunks, "i2jInvokeExactThunk", (intptr_t)startPC);9836#endif9837deleteMethodHandleRef(mhDetails, vmThread, trvm);9838}9839else // TODO:JSR292: Handle compile failures gracefully9840{9841}9842}98439844if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)9845{9846if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)9847jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;98489849dataCache = (TR_DataCache*)comp->getReservedDataCache();9850if (dataCache)9851{9852dataCache->resetAllocationToMark();9853// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)9854TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);9855comp->setReservedDataCache(NULL);9856}9857}98589859return startPC;9860}98619862J9Method *method = details.getMethod();98639864if (startPC) // if successful compilation9865{9866TR_ASSERT_FATAL(comp && entry, "comp object and entry must always exist when calling compilationEnd for a successful compilation");9867TR_ASSERT(vmThread, "We must always have a vmThread in compilationEnd()\n");9868#if defined(J9VM_OPT_JITSERVER)9869if (isJITServerMode)9870{9871outOfProcessCompilationEnd(entry, comp);9872}9873else9874#endif /* defined(J9VM_OPT_JITSERVER) */9875if (!(jitConfig->runtimeFlags & J9JIT_TOSS_CODE))9876{9877if (trvm->isAOT_DEPRECATED_DO_NOT_USE() && !entry->isRemoteCompReq())9878{9879// Committing AOT compilation that succeeded9880// We want to store AOT code in the cache9881#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))9882if (TR::Options::sharedClassCache())9883{9884J9JITExceptionTable *relocatedMetaData = NULL;9885const U_8 *dataStart;9886const U_8 *codeStart;9887UDATA dataSize, codeSize;98889889TR_ASSERT(comp, "AOT compilation that succeeded must have a compilation object");9890TR_ASSERT(comp->getAotMethodDataStart(), "The header must have been set");9891TR_AOTMethodHeader *aotMethodHeaderEntry = comp->getAotMethodHeaderEntry();98929893dataStart = (U_8 *)aotMethodHeaderEntry->compileMethodDataStartPC;9894dataSize = aotMethodHeaderEntry->compileMethodDataSize;9895codeStart = (U_8 *)aotMethodHeaderEntry->compileMethodCodeStartPC;9896codeSize = aotMethodHeaderEntry->compileMethodCodeSize;98979898aotMethodHeaderEntry->unused = TR::Compiler->host.is64Bit() ? 0xDEADC0DEDEADC0DEULL : 0xDEADC0DE;98999900J9ROMMethod *romMethod = comp->fej9()->getROMMethodFromRAMMethod(method);99019902TR::CompilationInfo::storeAOTInSharedCache(9903vmThread,9904romMethod,9905dataStart,9906dataSize,9907codeStart,9908codeSize,9909comp,9910jitConfig,9911entry9912);99139914#if defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT)99159916bool canRelocateMethod = TR::CompilationInfo::canRelocateMethod(comp);99179918if (canRelocateMethod)9919{9920J9JITDataCacheHeader *cacheEntry;99219922TR_ASSERT_FATAL(comp->cg(), "CodeGenerator must be allocated");99239924// Use same code cache as AOT compile9925//9926TR::CodeCache *aotMCCRuntimeCodeCache = comp->cg()->getCodeCache();9927TR_ASSERT(aotMCCRuntimeCodeCache, "Must have a reserved codeCache");9928cacheEntry = (J9JITDataCacheHeader *)dataStart;99299930// If compilation and/or slot monitors are held, they must now be released in order to call the9931// AOT relocation.9932//9933if (entry->getMonitor())9934{9935compInfo->debugPrint(vmThread, "\treleasing queue-slot monitor\n");9936compInfo->debugPrint(vmThread, "-AM\n");9937entry->releaseSlotMonitor(vmThread);9938}99399940compInfo->debugPrint(vmThread, "\treleasing compilation monitor\n");9941compInfo->debugPrint(vmThread, "-CM\n");9942compInfo->releaseCompMonitor(vmThread);9943int32_t returnCode = 0;99449945if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9946{9947TR_VerboseLog::writeLineLocked(9948TR_Vlog_DISPATCH,9949"Applying relocations to newly AOT compiled body for %s @ %s",9950comp->signature(),9951comp->getHotnessName()9952);9953}9954try9955{9956TR::CompilationInfoPerThreadBase::InterruptibleOperation(*entry->_compInfoPT);9957// need to get a non-shared cache VM to relocate9958TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, vmThread);9959TR_ResolvedMethod *compilee = fe->createResolvedMethod(comp->trMemory(), (TR_OpaqueMethodBlock *)method);9960relocatedMetaData = entry->_compInfoPT->reloRuntime()->prepareRelocateAOTCodeAndData(9961vmThread,9962fe,9963aotMCCRuntimeCodeCache,9964cacheEntry,9965method,9966true,9967comp->getOptions(),9968comp,9969compilee9970);9971returnCode = entry->_compInfoPT->reloRuntime()->returnCode();9972}9973catch (std::exception &e)9974{9975// Relocation Failure9976returnCode = compilationAotRelocationInterrupted;9977}99789979// Reacquire the compilation and/or slot monitors9980//9981compInfo->debugPrint(vmThread, "\tacquiring compilation monitor\n");9982compInfo->acquireCompMonitor(vmThread);9983compInfo->debugPrint(vmThread, "+CM\n");99849985if (entry->getMonitor())9986{9987// Acquire the queue slot monitor now9988//9989compInfo->debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");9990entry->acquireSlotMonitor(vmThread);9991compInfo->debugPrint(vmThread, "+AM-", entry);9992}99939994if (relocatedMetaData)9995{9996if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))9997{9998TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "Successfully relocated metadata for %s", comp->signature());9999}1000010001startPC = reinterpret_cast<void *>(relocatedMetaData->startPC);1000210003if (J9_EVENT_IS_HOOKED(jitConfig->javaVM->hookInterface, J9HOOK_VM_DYNAMIC_CODE_LOAD))10004{10005TR::CompilationInfo::addJ9HookVMDynamicCodeLoadForAOT(vmThread, method, jitConfig, relocatedMetaData);10006}10007jitMethodTranslated(vmThread, method, startPC);10008}10009else10010{10011entry->_doNotUseAotCodeFromSharedCache = true;10012entry->_compErrCode = returnCode;10013startPC = NULL;1001410015if (entry->_compilationAttemptsLeft > 0)10016{10017entry->_tryCompilingAgain = true;10018}1001910020if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance, TR_VerboseCompFailure))10021{10022TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,10023"Failure while relocating for %s, return code = %d [%s]\n",10024comp->signature(),10025returnCode,10026(returnCode >= 0) && (returnCode < compilationMaxError) ? compilationErrorNames[returnCode] : "unknown error");10027}10028}10029}1003010031/*10032* Method cannot be relocated or relocation has failed.10033*/10034if (!canRelocateMethod || !relocatedMetaData)10035{10036// Must reclaim code cache, metadata, jittedBodyInfo, persistentMethodInfo,10037// assumptions and RI records that could have been allocated.10038//10039TR_AOTMethodHeader *aotMethodHeaderEntry = comp->getAotMethodHeaderEntry();10040J9JITDataCacheHeader *cacheEntry = (J9JITDataCacheHeader *)aotMethodHeaderEntry->compileMethodDataStartPC;10041J9JITDataCacheHeader *exceptionTableCacheEntry = (J9JITDataCacheHeader *)((U_8 *)cacheEntry + aotMethodHeaderEntry->offsetToExceptionTable);10042J9JITExceptionTable *metaData = (J9JITExceptionTable *) (exceptionTableCacheEntry + 1);1004310044// The exception table is inserted in the AVL trees during the relocation10045// Since we didn't performed the relocation, we don't have to artifactManager->removeArtifact(metaData);1004610047// Delete any assumptions that might still exist in persistent memory10048// The metadata parameter is NULL meaning that we want to delete ALL assumptions, including those for JBI10049compInfo->getPersistentInfo()->getRuntimeAssumptionTable()->reclaimAssumptions(comp->getMetadataAssumptionList(), NULL);1005010051// reclaim code memory so we can use it for something else10052TR::CodeCacheManager::instance()->addFreeBlock(static_cast<void *>(metaData), reinterpret_cast<uint8_t *>(metaData->startPC));1005310054metaData->constantPool = 0; // mark metadata as unloaded1005510056TR_DataCache *dataCache = (TR_DataCache*)comp->getReservedDataCache();10057TR_ASSERT(dataCache, "A dataCache must be reserved for AOT compilations\n");10058// Make sure we didn't allocate a new dataCache (the mark was set in the old cache)10059TR_ASSERT(dataCache->getAllocationMark() == (uint8_t*)comp->getAotMethodDataStart(),10060"AllocationMark=%p does not match aotMethodDataStart=%p",10061dataCache->getAllocationMark(), comp->getAotMethodDataStart());10062dataCache->resetAllocationToMark();10063// Reservation will be cancelled at end of compilation1006410065// Inform that metadata is now NULL10066if (entry->_compInfoPT)10067entry->_compInfoPT->setMetadata(NULL);1006810069// mark that compilation failed10070startPC = oldStartPC;10071}10072#else10073/* If in the unlikely circumstance that AOT runtime support is off but AOT compilation occurred,10074* we should fail the compilation */10075jitMethodFailedTranslation(vmThread, method);10076#endif /* J9VM_INTERP_AOT_RUNTIME_SUPPORT */10077}10078else10079#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))10080{10081#ifdef AOT_DEBUG10082fprintf(stderr, "ERROR: AOT compiling but shared class is not available. Method will run interpreted\n");10083#endif10084TR_ASSERT(0, "shared classes flag not enabled yet we got an AOT compilation"); // This is a branch that is never expected to enter10085entry->_doNotUseAotCodeFromSharedCache = true;10086startPC = NULL;1008710088if (entry->_compilationAttemptsLeft > 0)10089{10090entry->_tryCompilingAgain = true;10091}1009210093if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance, TR_VerboseCompFailure))10094{10095TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Shared Class not available for AOT compile for %s", comp->signature());10096}10097}10098}10099else // Non-AOT compilation or remote JIT/AOT compilations (at the JITClient)10100{10101if ((trvm->isAOT_DEPRECATED_DO_NOT_USE()10102#if defined(J9VM_OPT_JITSERVER)10103|| comp->isDeserializedAOTMethod()10104#endif /* defined(J9VM_OPT_JITSERVER) */10105) && !TR::CompilationInfo::canRelocateMethod(comp))10106{10107// Handle the case when relocations are delayed.10108// Delete any assumptions that might still exist in persistent memory10109// The metadata parameter is NULL meaning that we want to delete ALL assumptions, including those for JBI10110J9JITExceptionTable *metaData = (J9JITExceptionTable *) comp->getAotMethodDataStart();10111if (metaData)10112{10113compInfo->getPersistentInfo()->getRuntimeAssumptionTable()->reclaimAssumptions(comp->getMetadataAssumptionList(), NULL);1011410115metaData->constantPool = 0; // mark metadata as unloaded10116}1011710118if (entry->_compInfoPT)10119entry->_compInfoPT->setMetadata(NULL);10120startPC = oldStartPC;10121}10122else10123{10124jitMethodTranslated(vmThread, method, startPC);10125}10126}10127}1012810129// If this is a retranslation, fix up the old method to forward to the new one10130//10131if (oldStartPC)10132{10133if (TR::Options::getVerboseOption(TR_VerboseCodeCache))10134{10135OMR::CodeCacheMethodHeader *oldMethodHeader = getCodeCacheMethodHeader((char*)oldStartPC, 32, NULL);10136OMR::CodeCacheMethodHeader *recompiledMethodHeader = getCodeCacheMethodHeader((char*)startPC, 32, NULL);10137UDATA oldEndPC = oldMethodHeader ? oldMethodHeader->_metaData->endPC : -1;10138UDATA endPC = recompiledMethodHeader ? recompiledMethodHeader->_metaData->endPC : -1;10139int oldMethodSize = oldMethodHeader ? (oldEndPC - (UDATA)oldStartPC + 1) : -1;10140int methodSize = recompiledMethodHeader ? (endPC - (UDATA)startPC + 1) : -1;1014110142TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Recompile %s @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT "(%d bytes) -> " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT "(%d bytes)", comp->signature(), oldStartPC, oldEndPC, oldMethodSize, startPC, endPC, methodSize);10143}1014410145TR::Recompilation::methodHasBeenRecompiled(oldStartPC, startPC, trvm);10146}10147}10148else if (!oldStartPC)10149{10150// Tell the VM that a non-compiled method failed translation10151//10152if (vmThread && entry && !entry->isOutOfProcessCompReq())10153jitMethodFailedTranslation(vmThread, method);10154#if defined(J9VM_OPT_JITSERVER)10155if (entry && isJITServerMode) // failure at the JITServer10156{10157// If no error code is set but the compilation failed,10158// it means the diagnostic JitDump compilation crashed.10159// We still need to notify the client, so manually set the error to compilationFailure10160if (entry->_compErrCode == compilationOK)10161entry->_compErrCode = compilationFailure;1016210163if (TR::Options::getVerboseOption(TR_VerboseJITServer))10164{10165TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,10166"compThreadID=%d has failed to compile: compErrCode %u %s",10167entry->_compInfoPT->getCompThreadId(), entry->_compErrCode, comp ? comp->signature() : "");10168}10169if (vmThread)10170Trc_JITServerFailedToCompile(vmThread, entry->_compInfoPT->getCompThreadId(), entry->_compErrCode,10171comp ? comp->signature() : "", comp ? comp->getHotnessName() : "");1017210173static bool breakAfterFailedCompile = feGetEnv("TR_breakAfterFailedCompile") != NULL;10174if (breakAfterFailedCompile)10175{10176fprintf(stderr, "\n=== Failed to compile %s ===\n", comp ? comp->signature() : "");10177TR::Compiler->debug.breakPoint();10178}10179int8_t compErrCode = entry->_compErrCode;10180if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)10181entry->_stream->writeError(compErrCode);10182}10183#endif /* defined(J9VM_OPT_JITSERVER) */10184}10185else // recompilation failure10186{10187// If this is a retranslation, fix up the old method to not try to recompile10188// again and return the oldStartPC as the new startPC so the old (fixed up)10189// method body is run10190//10191if (!isJITServerMode)10192TR::Recompilation::methodCannotBeRecompiled(oldStartPC, trvm);10193startPC = oldStartPC;10194#if defined(J9VM_OPT_JITSERVER)10195if (entry && isJITServerMode)10196{10197if (TR::Options::getVerboseOption(TR_VerboseJITServer))10198{10199TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,10200"compThreadID=%d has failed to recompile: compErrCode %u %s",10201entry->_compInfoPT->getCompThreadId(), entry->_compErrCode, comp ? comp->signature() : "");10202}10203if (vmThread)10204Trc_JITServerFailedToRecompile(vmThread, entry->_compInfoPT->getCompThreadId(), entry->_compErrCode,10205comp ? comp->signature() : "", comp ? comp->getHotnessName() : "");1020610207int8_t compErrCode = entry->_compErrCode;10208if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)10209entry->_stream->writeError(compilationNotNeeded);10210}10211#endif /* defined(J9VM_OPT_JITSERVER) */10212}1021310214if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)10215{10216if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)10217jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;1021810219dataCache = (TR_DataCache *)comp->getReservedDataCache();10220if (dataCache)10221{10222dataCache->resetAllocationToMark();10223// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)10224TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);10225comp->setReservedDataCache(NULL);10226}10227}1022810229return startPC;10230}1023110232// Ensure that only methods whose name (prefix) matches names in10233// the translation filter list are compiled.10234//10235bool10236TR::CompilationInfoPerThreadBase::methodCanBeCompiled(TR_Memory *trMemory, TR_FrontEnd * vm, TR_ResolvedMethod* method, TR_FilterBST * & filter)10237{10238filter = NULL;1023910240static char *dontCompileNatives = feGetEnv("TR_DontCompile");1024110242if (dontCompileNatives && (method->isNewInstanceImplThunk() || method->isJNINative()))10243{10244printf("don't compile because JNI or thunk\n");10245return false;10246}1024710248if (!method->isCompilable(trMemory))10249return false;1025010251char * methodName = method->nameChars();10252UDATA methodNameLen = method->nameLength();10253char * methodSig = method->signatureChars();10254UDATA methodSigLen = method->signatureLength();1025510256if (!(_jitConfig->runtimeFlags & J9JIT_COMPILE_CLINIT) &&10257methodNameLen == 8 && !J9OS_STRNCMP(methodName, "<clinit>", 8))10258return false;1025910260if (_jitConfig->bcSizeLimit && (method->maxBytecodeIndex() > _jitConfig->bcSizeLimit))10261return false;1026210263// if we've translated something that has transformed a newInstanceImpl call to virtual call10264// to a thunk. Then we have to compile the thunk.10265//10266if (method->isNewInstanceImplThunk())10267{10268TR_J9VMBase *fej9 = (TR_J9VMBase *)vm;10269// Do not compile thunks for arrays10270return !fej9->isClassArray(method->classOfMethod());10271}1027210273if (!TR::Options::getDebug())10274return true;1027510276return TR::Options::getDebug()->methodCanBeCompiled(trMemory, method, filter);10277}1027810279void TR::CompilationInfoPerThreadBase::logCompilationSuccess(10280J9VMThread * vmThread,10281TR_J9VMBase &vm,10282J9Method * method,10283TR::SegmentAllocator const &scratchSegmentProvider,10284TR_ResolvedMethod * compilee,10285TR::Compilation * compiler,10286TR_MethodMetaData * metaData,10287TR_OptimizationPlan * optimizationPlan10288)10289{10290if (!_methodBeingCompiled->isAotLoad())10291{10292J9JavaVM * javaVM = _jitConfig->javaVM;10293// Dump mixed mode disassembly listing.10294//10295if (compiler->getOutFile() != NULL && compiler->getOption(TR_TraceAll))10296compiler->getDebug()->dumpMixedModeDisassembly();1029710298if (!vm.isAOT_DEPRECATED_DO_NOT_USE())10299{10300if (J9_EVENT_IS_HOOKED(javaVM->hookInterface, J9HOOK_VM_DYNAMIC_CODE_LOAD))10301{10302OMR::CodeCacheMethodHeader *ccMethodHeader;10303ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(javaVM->hookInterface, vmThread, method, (U_8*)metaData->startPC, metaData->endWarmPC - metaData->startPC, "JIT warm body", metaData);1030410305if (metaData->startColdPC)10306{10307// Register the cold code section too10308//10309ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(javaVM->hookInterface, vmThread, method, (U_8*)metaData->startColdPC, metaData->endPC - metaData->startColdPC, "JIT cold body", metaData);10310}10311ccMethodHeader = getCodeCacheMethodHeader((char *)metaData->startPC, 32, metaData);10312if (ccMethodHeader && (metaData->bodyInfo != NULL))10313{10314J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get((void *)metaData->startPC);10315if (linkageInfo->isRecompMethodBody())10316{10317ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(javaVM->hookInterface, vmThread, method, (void *)((char*)ccMethodHeader->_eyeCatcher+4), metaData->startPC - (UDATA)((char*)ccMethodHeader->_eyeCatcher+4), "JIT method header", metaData);10318}10319}10320}10321}1032210323PORT_ACCESS_FROM_JITCONFIG(_jitConfig);10324UDATA translationTime = j9time_usec_clock() - getTimeWhenCompStarted();10325if (TR::Options::_largeTranslationTime > 0 && translationTime > (UDATA)(TR::Options::_largeTranslationTime))10326{10327if (compiler->getOutFile() != NULL)10328trfprintf(compiler->getOutFile(), "Compilation took %d usec\n", (int32_t)translationTime);10329compiler->dumpMethodTrees("Post optimization trees for large computing method");10330}10331if (_onSeparateThread)10332{10333TR::CompilationInfoPerThread *cipt = (TR::CompilationInfoPerThread*)this;10334cipt->setLastCompilationDuration(translationTime / 1000);10335}1033610337UDATA gcDataBytes = _jitConfig->lastGCDataAllocSize;10338UDATA atlasBytes = _jitConfig->lastExceptionTableAllocSize;1033910340// Statistics for number of aoted methods that were recompiled10341//10342if (_methodBeingCompiled->_oldStartPC != 0) // this is a recompilation10343{10344TR_PersistentJittedBodyInfo *oldBodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(_methodBeingCompiled->_oldStartPC);10345// because this is a recompilation, the persistentJittedBodyInfo must exist10346if (oldBodyInfo->getIsAotedBody())10347_compInfo._statNumAotedMethodsRecompiled++;1034810349// Statistics about Recompilations for bodies with Jprofiling10350if (oldBodyInfo->getUsesJProfiling())10351{10352if (compiler->getRecompilationInfo() &&10353compiler->getRecompilationInfo()->getJittedBodyInfo()->getMethodInfo()->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToJProfiling)10354_compInfo._statNumRecompilationForBodiesWithJProfiling++;10355}10356}10357// Statistics for compilations from LPQ10358if (_methodBeingCompiled->_reqFromSecondaryQueue)10359_compInfo.getLowPriorityCompQueue().incStatsCompFromLPQ(_methodBeingCompiled->_reqFromSecondaryQueue);1036010361// Statistics about SamplingJProfiling bodies10362if (compiler->getRecompilationInfo() &&10363compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesSamplingJProfiling())10364_compInfo._statNumSamplingJProfilingBodies++;1036510366// Statistics about JProfiling bodies10367if (compiler->getRecompilationInfo() &&10368compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesJProfiling())10369_compInfo._statNumJProfilingBodies++;1037010371// Statistics about number of methods taken from the queue with JProfiling requests10372if (_methodBeingCompiled->_reqFromJProfilingQueue)10373_compInfo._statNumMethodsFromJProfilingQueue++;1037410375if (_jitConfig->runtimeFlags & J9JIT_TOSS_CODE)10376{10377TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "JIT %s OK\n", compiler->signature());10378}10379else10380{10381char compilationTypeString[15] = { 0 };10382TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",10383vm.isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",10384compiler->isProfilingCompilation() ? "profiled " : "");1038510386UDATA startPC = 0;10387UDATA endWarmPC = 0;10388UDATA startColdPC = 0;10389UDATA endPC = 0;10390if (metaData)10391{10392startPC = metaData->startPC;10393startColdPC = metaData->startColdPC;10394endWarmPC = metaData->endWarmPC;10395endPC = metaData->endPC;10396}1039710398TR_Hotness h = compiler->getMethodHotness();10399if (h < numHotnessLevels)10400{10401_compInfo._statsOptLevels[(int32_t)h]++;10402#if defined(J9VM_OPT_JITSERVER)10403if(_methodBeingCompiled->isRemoteCompReq())10404_compInfo._statsRemoteOptLevels[(int32_t)h]++;10405#endif /* defined(J9VM_OPT_JITSERVER) */10406}10407if (compilee->isJNINative())10408_compInfo._statNumJNIMethodsCompiled++;10409const char * hotnessString = compiler->getHotnessName(h);10410TR_ASSERT(hotnessString, "expected to have a hotness string");1041110412const char * prexString = compiler->usesPreexistence() ? " prex" : "";1041310414int32_t profilingCount = 0, profilingFrequencey = 0, counter = 0;10415if (compiler->isProfilingCompilation())10416{10417TR::Recompilation *recompInfo = compiler->getRecompilationInfo();10418profilingCount = recompInfo->getProfilingCount();10419profilingFrequencey = recompInfo->getProfilingFrequency();10420counter = recompInfo->getJittedBodyInfo()->getCounter(); // profiling invocation count10421}1042210423char recompReason = '-';10424// For recompiled methods try to find the reason for recompilation10425if (_methodBeingCompiled->_oldStartPC)10426{10427TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(_methodBeingCompiled->_oldStartPC);10428if (bodyInfo->getIsInvalidated())10429{10430recompReason = 'I'; // method was invalidated10431}10432else10433{10434switch (bodyInfo->getMethodInfo()->getReasonForRecompilation())10435{10436case TR_PersistentMethodInfo::RecompDueToThreshold:10437recompReason = 'T'; break;10438case TR_PersistentMethodInfo::RecompDueToCounterZero:10439recompReason = 'Z'; break;10440case TR_PersistentMethodInfo::RecompDueToMegamorphicCallProfile:10441recompReason = 'M'; break;10442case TR_PersistentMethodInfo::RecompDueToOptLevelUpgrade:10443recompReason = 'C'; break;10444case TR_PersistentMethodInfo::RecompDueToSecondaryQueue:10445recompReason = 'S'; break;10446case TR_PersistentMethodInfo::RecompDueToForcedAOTUpgrade:10447recompReason = 'A'; break;10448case TR_PersistentMethodInfo::RecompDueToRI:10449recompReason = 'R'; break;10450case TR_PersistentMethodInfo::RecompDueToJProfiling:10451recompReason = 'J'; break;10452case TR_PersistentMethodInfo::RecompDueToInlinedMethodRedefinition:10453recompReason = 'H'; break;10454case TR_PersistentMethodInfo::RecompDueToGCR:10455if (compiler->getOption(TR_NoOptServer))10456recompReason = 'g';// Guarded counting recompilation10457else10458recompReason = 'G';// Guarded counting recompilation10459_compInfo._statNumGCRInducedCompilations++;10460break;10461// TODO: add here the EDO case if we ever modify the codegen to track that10462} // end switch10463bodyInfo->getMethodInfo()->setReasonForRecompilation(0); // reset the flags10464}10465}1046610467// If set, print verbose compile results, gc/exception, and/or time.10468if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseGc, TR_VerboseRecompile, TR_VerbosePerformance, TR_VerboseOptimizer)10469|| (compiler->getOption(TR_CountOptTransformations) && compiler->getVerboseOptTransformationCount() >= 1))10470{10471const uint32_t bytecodeSize = TR::CompilationInfo::getMethodBytecodeSize(method);10472const bool isJniNative = compilee->isJNINative();10473TR_VerboseLog::CriticalSection vlogLock;10474TR_VerboseLog::write(TR_Vlog_COMP,"(%s%s) %s @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT,10475compilationTypeString,10476hotnessString,10477compiler->signature(),10478startPC,10479startColdPC ? endWarmPC : endPC);1048010481if (startColdPC)10482{10483TR_VerboseLog::write("/" POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT, startColdPC, endPC);10484}1048510486j9jit_printf(_jitConfig, " %s", _methodBeingCompiled->getMethodDetails().name());1048710488// Print recompilation reason10489// For methods compiled through sample thresholds, print also the CPU utilization10490if (recompReason == 'T')10491TR_VerboseLog::write(" %.2f%%", optimizationPlan->getPerceivedCPUUtil() / 10.0);1049210493TR_VerboseLog::write(" %c", recompReason);10494TR_VerboseLog::write(" Q_SZ=%d Q_SZI=%d QW=%d", _compInfo.getMethodQueueSize(),10495_compInfo.getNumQueuedFirstTimeCompilations(), _compInfo.getQueueWeight());1049610497TR_VerboseLog::write(" j9m=%p bcsz=%u", method, bytecodeSize);1049810499if (!_methodBeingCompiled->_async)10500TR_VerboseLog::write(" sync"); // flag the synchronous compilations1050110502if (isJniNative)10503TR_VerboseLog::write(" JNI"); // flag JNI compilations1050410505if (compiler->getOption(TR_EnableOSR))10506TR_VerboseLog::write(" OSR");1050710508if (compiler->getRecompilationInfo() && compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesGCR())10509TR_VerboseLog::write(" GCR");1051010511if (compiler->getRecompilationInfo() && (compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesSamplingJProfiling() || compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesJProfiling()))10512TR_VerboseLog::write(" JPROF");1051310514if (compiler->isDLT())10515TR_VerboseLog::write(" DLT@%d", compiler->getDltBcIndex());1051610517if (_methodBeingCompiled->_reqFromSecondaryQueue)10518TR_VerboseLog::write(" LPQ");1051910520if (_methodBeingCompiled->_reqFromJProfilingQueue)10521TR_VerboseLog::write(" JPQ");1052210523#if defined(J9VM_OPT_JITSERVER)10524if (_methodBeingCompiled->isRemoteCompReq())10525{10526TR_VerboseLog::write(" remote");10527if (compiler->isDeserializedAOTMethod())10528TR_VerboseLog::write(" deserialized");10529}10530#endif /* defined(J9VM_OPT_JITSERVER) */1053110532if (TR::Options::getVerboseOption(TR_VerboseGc))10533{10534TR_VerboseLog::write(" gc=%d atlas=%d", gcDataBytes, atlasBytes);10535}1053610537if (TR::Options::getVerboseOption(TR_VerbosePerformance))10538TR_VerboseLog::write(" time=%dus", translationTime);1053910540if (TR::Options::getVerboseOption(TR_VerbosePerformance))10541{10542TR_VerboseLog::write(10543" mem=[region=%llu system=%llu]KB",10544static_cast<unsigned long long>(scratchSegmentProvider.regionBytesAllocated())/1024,10545static_cast<unsigned long long>(scratchSegmentProvider.systemBytesAllocated())/1024);10546}1054710548#if defined(WINDOWS) && defined(TR_TARGET_32BIT)10549if (TR::Options::getVerboseOption(TR_VerboseVMemAvailable))10550{10551J9MemoryInfo memInfo;10552PORT_ACCESS_FROM_JITCONFIG(_jitConfig);10553if (j9sysinfo_get_memory_info(&memInfo) == 0 &&10554memInfo.availVirtual != J9PORT_MEMINFO_NOT_AVAILABLE)10555TR_VerboseLog::write(" VMemAv=%u MB", static_cast<uint32_t>(memInfo.availVirtual >> 20));10556}10557#endif10558if (TR::Options::getVerboseOption(TR_VerboseRecompile))10559{10560TR_VerboseLog::write("%s [profiling c(%d), f(%d), ivc(%d)]", prexString, profilingCount, profilingFrequencey, counter);10561}1056210563if (compiler->getOption(TR_CountOptTransformations) && compiler->getOption(TR_VerboseOptTransformations))10564{10565TR_VerboseLog::write(" transformations=%d", compiler->getVerboseOptTransformationCount());10566}1056710568if (TR::Options::getVerboseOption(TR_VerboseOptimizer))10569{10570TR_VerboseLog::write(" opts=%d.%d", compiler->getLastPerformedOptIndex(), compiler->getLastPerformedOptSubIndex());10571}1057210573if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance))10574{10575TR_VerboseLog::write(" compThreadID=%d", compiler->getCompThreadID());10576}1057710578// print cached cpu usage (sampled elsewhere [samplerThreadProc])1057910580CpuUtilization *cpuUtil = _compInfo.getCpuUtil();10581if (cpuUtil->isFunctional())10582{10583TR_VerboseLog::write(" CpuLoad=%d%%(%d%%avg) JvmCpu=%d%%",10584cpuUtil->getCpuUsage(),10585cpuUtil->getAvgCpuUsage(),10586cpuUtil->getVmCpuUsage());10587}1058810589if (TR::Options::getVerboseOption(TR_VerboseCompilationThreads) && _onSeparateThread)10590{10591// CPU spent in comp thread is quite coarse (updated every 0.5 sec)10592// We could use getCpuTimeNow() if we wanted to be more accurate10593TR::CompilationInfoPerThread *cipt = (TR::CompilationInfoPerThread*)this;10594int32_t cpuUtil = cipt->getCompThreadCPU().getThreadLastCpuUtil();10595if (cpuUtil >= 0)10596TR_VerboseLog::write(" compCPU=%d%%", cpuUtil);10597}1059810599TR_VerboseLog::writeLine("");10600}1060110602char compilationAttributes[40] = { 0 };10603TR::snprintfNoTrunc(compilationAttributes, sizeof(compilationAttributes), "%s %s %s %s %s %s %s",10604prexString,10605!_methodBeingCompiled->_async ? "sync" : "",10606compilee->isJNINative()? "JNI" : "",10607compiler->getOption(TR_EnableOSR) ? "OSR" : "",10608(compiler->getRecompilationInfo() && compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesGCR()) ? "GCR" : "",10609compiler->isDLT() ? "DLT" : "",10610TR::CompilationInfo::isJSR292(method) ? "JSR292" : ""10611);1061210613Trc_JIT_compileEnd15(vmThread, compilationTypeString, hotnessString, compiler->signature(),10614startPC, endWarmPC, startColdPC, endPC,10615translationTime, method, metaData,10616recompReason, _compInfo.getMethodQueueSize(), TR::CompilationInfo::getMethodBytecodeSize(method),10617static_cast<uint32_t>(10618(scratchSegmentProvider.systemBytesAllocated() / 1024) & static_cast<uint32_t>(-1)10619),10620compilationAttributes);1062110622#ifdef TR_HOST_S39010623if (TR::Options::getVerboseOption(TR_VerboseMMap))10624{10625outputVerboseMMapEntries(compilee, metaData, compilationTypeString, hotnessString);10626}1062710628#endif // ifdef TR_HOST_S39010629}10630}10631}1063210633static void10634printCompFailureInfo(TR::Compilation * comp, const char * reason)10635{10636if (comp && comp->getOptions()->getAnyOption(TR_TraceAll))10637traceMsg(comp, "\n=== EXCEPTION THROWN (%s) ===\n", reason);10638}1063910640void10641TR::CompilationInfoPerThreadBase::processException(10642J9VMThread *vmThread,10643TR::SegmentAllocator const &scratchSegmentProvider,10644TR::Compilation * compiler,10645volatile bool & haveLockedClassUnloadMonitor,10646const char *exceptionName10647) throw()10648{10649if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))10650{10651TR_VerboseLog::writeLineLocked(10652TR_Vlog_DISPATCH,10653"Failed to finalize compiled body for %s @ %s",10654compiler->signature(),10655compiler->getHotnessName()10656);10657}1065810659OMR::RuntimeAssumption **metadataAssumptionList = compiler->getMetadataAssumptionList();10660if (metadataAssumptionList && (*metadataAssumptionList))10661{10662compiler->getPersistentInfo()->getRuntimeAssumptionTable()->reclaimAssumptions(metadataAssumptionList, NULL);10663}1066410665// Defect 194113 - still holding schedule monitor at this point, release it!10666//10667while (((TR::Monitor *)getCompilationInfo()->_schedulingMonitor)->owned_by_self())10668getCompilationInfo()->_schedulingMonitor->exit(); //the if monitor is still held, release1066910670if (!compiler->getOption(TR_DisableNoVMAccess))10671{10672if (haveLockedClassUnloadMonitor)10673{10674// On the exception path the monitor may not be held10675// Do a test first, otherwise an internal assume will be triggered10676//10677if (TR::MonitorTable::get()->getClassUnloadMonitorHoldCount(getCompThreadId()) > 0)10678TR::MonitorTable::get()->readReleaseClassUnloadMonitor(getCompThreadId());10679}1068010681if (!(vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS))10682acquireVMAccessNoSuspend(vmThread);10683}1068410685if (TR::Options::getVerboseOption(TR_VerboseCompYieldStats))10686{10687if (compiler->getMaxYieldInterval() > TR::Options::_compYieldStatsThreshold)10688{10689TR_VerboseLog::CriticalSection vlogLock;10690compiler->printCompYieldStats();10691}10692}1069310694PORT_ACCESS_FROM_JITCONFIG(_jitConfig);1069510696bool shouldProcessExceptionCommonTasks = true;1069710698try10699{10700throw;10701}1070210703// The catch blocks below are ordered such that in each group of10704// blocks, the least derived type is at the end of the group.1070510706/* Allocation Exceptions Start */10707catch (const TR::RecoverableCodeCacheError &e)10708{10709if (compiler->compileRelocatableCode())10710_methodBeingCompiled->_compErrCode = compilationAotCacheFullReloFailure;10711else10712_methodBeingCompiled->_compErrCode = compilationRecoverableCodeCacheError;10713}10714catch (const TR::CodeCacheError &e)10715{10716_methodBeingCompiled->_compErrCode = compilationCodeCacheError;10717}10718catch (const J9::RecoverableDataCacheError &e)10719{10720TR_ASSERT(compiler->compileRelocatableCode(),10721"Only AOT compiles should throw a J9::RecoverableDataCacheError exception\n");10722if (compiler->compileRelocatableCode())10723_methodBeingCompiled->_compErrCode = compilationAotCacheFullReloFailure;10724else10725_methodBeingCompiled->_compErrCode = compilationDataCacheError;10726}10727catch (const J9::DataCacheError &e)10728{10729_methodBeingCompiled->_compErrCode = compilationDataCacheError;10730}10731catch (const TR::RecoverableTrampolineError &e)10732{10733_methodBeingCompiled->_compErrCode = compilationRecoverableTrampolineFailure;10734}10735catch (const TR::TrampolineError &e)10736{10737_methodBeingCompiled->_compErrCode = compilationTrampolineFailure;10738}10739catch (const J9::LowPhysicalMemory &e)10740{10741_methodBeingCompiled->_compErrCode = compilationLowPhysicalMemory;10742}10743catch (const std::bad_alloc &e)10744{10745_methodBeingCompiled->_compErrCode = compilationHeapLimitExceeded;10746}10747/* Allocation Exceptions End */1074810749/* IL Gen Exceptions Start */10750catch (const J9::AOTHasInvokeHandle &e)10751{10752_methodBeingCompiled->_compErrCode = compilationAotHasInvokehandle;10753}10754catch (const J9::AOTHasInvokeVarHandle &e)10755{10756_methodBeingCompiled->_compErrCode = compilationAotHasInvokeVarHandle;10757}10758catch (const J9::AOTHasInvokeSpecialInInterface &e)10759{10760_methodBeingCompiled->_compErrCode = compilationAotHasInvokeSpecialInterface;10761}10762catch (const J9::FSDHasInvokeHandle &e)10763{10764_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;10765}10766catch (const J9::AOTHasPatchedCPConstant &e)10767{10768_methodBeingCompiled->_compErrCode = compilationAotPatchedCPConstant;10769}10770catch (const TR::NoRecompilationRecoverableILGenException &e)10771{10772_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;10773}10774catch (const TR::ILGenFailure &e)10775{10776_methodBeingCompiled->_compErrCode = compilationILGenFailure;10777}10778catch (const TR::UnsupportedValueTypeOperation &e)10779{10780_methodBeingCompiled->_compErrCode = compilationILGenUnsupportedValueTypeOperationFailure;10781}10782/* IL Gen Exceptions End */1078310784/* Runtime Failure Exceptions Start */10785catch (const J9::CHTableCommitFailure &e)10786{10787_methodBeingCompiled->_compErrCode = compilationCHTableCommitFailure;10788}10789catch (const J9::MetaDataCreationFailure &e)10790{10791_methodBeingCompiled->_compErrCode = compilationMetaDataFailure;10792}10793catch (const J9::AOTRelocationFailed &e)10794{10795// no need to set error code here because error code is set10796// in installAotCachedMethod when the relocation failed10797}10798/* Runtime Failure Exceptions End */1079910800/* Insufficiently Aggressive Compilation Exceptions Start */10801catch (const J9::LambdaEnforceScorching &e)10802{10803_methodBeingCompiled->_compErrCode = compilationLambdaEnforceScorching;10804}10805catch (const J9::EnforceProfiling &e)10806{10807_methodBeingCompiled->_compErrCode = compilationEnforceProfiling;10808}10809catch (const TR::InsufficientlyAggressiveCompilation &e)10810{10811_methodBeingCompiled->_compErrCode = compilationNeededAtHigherLevel;10812}10813/* Insufficiently Aggressive Compilation Exceptions End */1081410815/* Excessive Complexity Exceptions Start */10816catch (const TR::ExcessiveComplexity &e)10817{10818_methodBeingCompiled->_compErrCode = compilationExcessiveComplexity;10819}10820catch (const TR::MaxCallerIndexExceeded &e)10821{10822_methodBeingCompiled->_compErrCode = compilationMaxCallerIndexExceeded;10823}10824/* Excessive Complexity Exceptions End */1082510826catch (const TR::CompilationInterrupted &e)10827{10828_methodBeingCompiled->_compErrCode = compilationInterrupted;10829}10830catch (const TR::UnimplementedOpCode &e)10831{10832_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;10833}10834catch (const TR::GCRPatchFailure &e)10835{10836_methodBeingCompiled->_compErrCode = compilationGCRPatchFailure;10837}10838catch (const J9::AOTSymbolValidationManagerFailure &e)10839{10840_methodBeingCompiled->_compErrCode = compilationSymbolValidationManagerFailure;10841}10842catch (const J9::AOTNoSupportForAOTFailure &e)10843{10844_methodBeingCompiled->_compErrCode = compilationAOTNoSupportForAOTFailure;10845}10846catch (const J9::AOTRelocationRecordGenerationFailure &e)10847{10848_methodBeingCompiled->_compErrCode = compilationAOTRelocationRecordGenerationFailure;10849}10850catch (const J9::ClassChainPersistenceFailure &e)10851{10852shouldProcessExceptionCommonTasks = false;10853_methodBeingCompiled->_compErrCode = compilationCHTableCommitFailure;10854if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))10855{10856uintptr_t translationTime = j9time_usec_clock() - getTimeWhenCompStarted(); //get the time it took to fail the compilation10857char compilationTypeString[15] = { 0 };10858TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",10859compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",10860compiler->isProfilingCompilation() ? "profiled " : "");10861TR_VerboseLog::writeLineLocked(10862TR_Vlog_COMPFAIL,10863"(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus %s compThreadID=%d",10864compilationTypeString,10865compiler->getHotnessName(compiler->getMethodHotness()),10866compiler->signature(),10867_compInfo.getMethodQueueSize(),10868_compInfo.getNumQueuedFirstTimeCompilations(),10869_compInfo.getQueueWeight(),10870_methodBeingCompiled->getMethodDetails().getMethod(),10871translationTime,10872"Class chain persistence failure",10873getCompThreadId()10874);10875}10876Trc_JIT_compilationFailed(vmThread, compiler->signature(), -1);10877}10878catch (const TR::AssertionFailure &e)10879{10880shouldProcessExceptionCommonTasks = false;10881if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))10882{10883uintptr_t translationTime = j9time_usec_clock() - getTimeWhenCompStarted(); //get the time it took to fail the compilation10884char compilationTypeString[15] = { 0 };10885TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",10886compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",10887compiler->isProfilingCompilation() ? "profiled " : "");10888// This assertion will only be generated in production, when softFailOnAssumes is set.10889TR_VerboseLog::writeLineLocked(10890TR_Vlog_COMPFAIL,10891"(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus Assertion Failure compThreadID=%d",10892compilationTypeString,10893compiler->getHotnessName(compiler->getMethodHotness()),10894compiler->signature(),10895_compInfo.getMethodQueueSize(),10896_compInfo.getNumQueuedFirstTimeCompilations(),10897_compInfo.getQueueWeight(),10898_methodBeingCompiled->getMethodDetails().getMethod(),10899translationTime,10900getCompThreadId()10901);10902}10903Trc_JIT_compilationFailed(vmThread, compiler->signature(), -1);10904}10905#if defined(J9VM_OPT_JITSERVER)10906catch (const JITServer::StreamFailure &e)10907{10908if (TR::Options::getVerboseOption(TR_VerboseJITServer))10909TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamFailure: %s", getCompThreadId(), e.what());10910Trc_JITServerStreamFailure(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());10911_methodBeingCompiled->_compErrCode = compilationStreamFailure;10912}10913catch (const JITServer::StreamInterrupted &e)10914{10915if (TR::Options::getVerboseOption(TR_VerboseJITServer))10916TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamInterrupted: %s", getCompThreadId(), e.what());10917Trc_JITServerStreamInterrupted(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());10918_methodBeingCompiled->_compErrCode = compilationStreamInterrupted;10919}10920catch (const JITServer::StreamVersionIncompatible &e)10921{10922if (TR::Options::getVerboseOption(TR_VerboseJITServer))10923TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamVersionIncompatible: %s", getCompThreadId(), e.what());10924Trc_JITServerStreamVersionIncompatible(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());10925_methodBeingCompiled->_compErrCode = compilationStreamVersionIncompatible;10926}10927catch (const JITServer::StreamMessageTypeMismatch &e)10928{10929if (TR::Options::getVerboseOption(TR_VerboseJITServer))10930TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamMessageTypeMismatch: %s", getCompThreadId(), e.what());10931Trc_JITServerStreamMessageTypeMismatch(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());10932_methodBeingCompiled->_compErrCode = compilationStreamMessageTypeMismatch;10933}10934catch (const JITServer::ServerCompilationFailure &e)10935{10936// no need to set error code here because error code is set10937// in remoteCompile at JITClient when the compilation failed.10938}10939catch (const J9::AOTCacheDeserializationFailure &e)10940{10941// error code was already set in remoteCompile()10942}10943#endif /* defined(J9VM_OPT_JITSERVER) */10944catch (...)10945{10946_methodBeingCompiled->_compErrCode = compilationFailure;10947}1094810949if (shouldProcessExceptionCommonTasks)10950processExceptionCommonTasks(vmThread, scratchSegmentProvider, compiler, exceptionName);1095110952TR::IlGeneratorMethodDetails & details = _methodBeingCompiled->getMethodDetails();10953J9Method *method = details.getMethod();10954TRIGGER_J9HOOK_JIT_COMPILING_END(_jitConfig->hookInterface, vmThread, method);10955}1095610957void10958TR::CompilationInfoPerThreadBase::processExceptionCommonTasks(10959J9VMThread *vmThread,10960TR::SegmentAllocator const &scratchSegmentProvider,10961TR::Compilation * compiler,10962const char *exceptionName10963)10964{10965PORT_ACCESS_FROM_JITCONFIG(_jitConfig);1096610967if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))10968{10969uintptr_t translationTime = j9time_usec_clock() - getTimeWhenCompStarted(); //get the time it took to fail the compilation1097010971char compilationTypeString[15] = { 0 };10972TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",10973compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",10974compiler->isProfilingCompilation() ? "profiled " : "");1097510976const char *hotnessString = compiler->getHotnessName(compiler->getMethodHotness());1097710978TR_VerboseLog::CriticalSection vlogLock;10979if (_methodBeingCompiled->_compErrCode != compilationFailure)10980{10981if ((_jitConfig->runtimeFlags & J9JIT_TOSS_CODE) && _methodBeingCompiled->_compErrCode == compilationInterrupted)10982{10983TR_VerboseLog::write(TR_Vlog_FAILURE, "Translating %s j9m=%p time=%dus-- Interrupted because of %s",10984compiler->signature(), _methodBeingCompiled->getMethodDetails().getMethod(), translationTime, exceptionName);10985}10986else10987{10988TR_VerboseLog::write(TR_Vlog_COMPFAIL, "(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus %s memLimit=%zu KB",10989compilationTypeString,10990hotnessString,10991compiler->signature(),10992_compInfo.getMethodQueueSize(),10993_compInfo.getNumQueuedFirstTimeCompilations(),10994_compInfo.getQueueWeight(),10995_methodBeingCompiled->getMethodDetails().getMethod(),10996translationTime,10997compilationErrorNames[_methodBeingCompiled->_compErrCode],10998scratchSegmentProvider.allocationLimit() >> 10);10999if (TR::Options::getVerboseOption(TR_VerbosePerformance))11000{11001bool incomplete;11002uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incomplete);11003if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE)11004TR_VerboseLog::write(" freePhysicalMemory=%llu MB", freePhysicalMemorySizeB >> 20);11005}11006}11007}11008else11009{11010TR_VerboseLog::write(TR_Vlog_COMPFAIL, "(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus <TRANSLATION FAILURE: %s>",11011compilationTypeString,11012hotnessString,11013compiler->signature(),11014_compInfo.getMethodQueueSize(),11015_compInfo.getNumQueuedFirstTimeCompilations(),11016_compInfo.getQueueWeight(),11017_methodBeingCompiled->getMethodDetails().getMethod(),11018translationTime,11019exceptionName);11020}1102111022if (TR::Options::getVerboseOption(TR_VerbosePerformance))11023{11024TR_VerboseLog::write(11025" mem=[region=%llu system=%llu]KB",11026static_cast<unsigned long long>(scratchSegmentProvider.regionBytesAllocated())/1024,11027static_cast<unsigned long long>(scratchSegmentProvider.systemBytesAllocated())/1024);11028}11029TR_VerboseLog::writeLine(" compThreadID=%d", compiler->getCompThreadID());11030}1103111032if(_methodBeingCompiled->_compErrCode == compilationFailure)11033{11034Trc_JIT_outOfMemory(vmThread);11035}11036else11037{11038Trc_JIT_compilationFailed(vmThread, compiler->signature(), -1);11039}11040}1104111042void TR::CompilationInfo::printCompQueue()11043{11044fprintf(stderr, "\nQueue:");11045for (TR_MethodToBeCompiled *cur = _methodQueue; cur; cur = cur->_next)11046{11047fprintf(stderr, " %p", cur);11048}11049fprintf(stderr, "\n");11050}1105111052#if DEBUG11053void11054TR::CompilationInfo::debugPrint(char * debugString)11055{11056if (!_traceCompiling)11057return;11058fprintf(stderr, "%s", debugString);11059}1106011061void11062TR::CompilationInfo::debugPrint(J9VMThread * vmThread, char * debugString)11063{11064if (!_traceCompiling)11065return;11066fprintf(stderr, "%8" OMR_PRIxPTR ":", (uintptr_t)vmThread);11067fprintf(stderr, "%s", debugString);11068}1106911070void11071TR::CompilationInfo::debugPrint(char * debugString, intptr_t val)11072{11073if (!_traceCompiling)11074return;11075fprintf(stderr, debugString, val);11076}1107711078void11079TR::CompilationInfo::debugPrint(J9VMThread * vmThread, char * debugString, IDATA val)11080{11081if (!_traceCompiling)11082return;11083fprintf(stderr, "%8" OMR_PRIxPTR ":", (uintptr_t)vmThread);11084fprintf(stderr, debugString, val);11085}1108611087void11088TR::CompilationInfo::debugPrint(J9Method * method)11089{11090if (!_traceCompiling)11091return;11092if (!method)11093{11094fprintf(stderr, "none");11095return;11096}11097J9UTF8 *className;11098J9UTF8 *name;11099J9UTF8 *signature;11100getClassNameSignatureFromMethod(method, className, name, signature);11101fprintf(stderr, "%.*s.%.*s%.*s", J9UTF8_LENGTH(className), (char *) J9UTF8_DATA(className),11102J9UTF8_LENGTH(name), (char *) J9UTF8_DATA(name),11103J9UTF8_LENGTH(signature), (char *) J9UTF8_DATA(signature));11104}1110511106void11107TR::CompilationInfo::debugPrint(char * debugString, J9Method * method)11108{11109if (!_traceCompiling)11110return;11111fprintf(stderr, "%s for method ", debugString);11112debugPrint(method);11113fprintf(stderr, "\n");11114}1111511116void11117TR::CompilationInfo::debugPrint(char * debugString, TR::IlGeneratorMethodDetails & details, J9VMThread * vmThread)11118{11119if (!_traceCompiling)11120return;11121fprintf(stderr, "%8" OMR_PRIxPTR ":", (uintptr_t)vmThread);11122if (details.isNewInstanceThunk())11123{11124J9Class *classForNewInstance = static_cast<J9::NewInstanceThunkDetails &>(details).classNeedingThunk();11125fprintf(stderr, "%s for newInstanceThunk ", debugString);11126int32_t len;11127TR_J9VMBase * fej9 = TR_J9VMBase::get(_jitConfig, vmThread);11128char * className = fej9->getClassNameChars(fej9->convertClassPtrToClassOffset(classForNewInstance), len);11129fprintf(stderr, "%.*s.newInstancePrototype(Ljava/lang/Class;)Ljava/lang/Object;\n", len, className);11130}11131else11132{11133fprintf(stderr, "%s for method ",debugString);11134debugPrint(details.getMethod());11135fprintf(stderr, "\n");11136}11137}1113811139void11140TR::CompilationInfo::debugPrint(J9VMThread * vmThread, char * msg, TR_MethodToBeCompiled *entry)11141{11142if (!_traceCompiling)11143return;11144fprintf(stderr, "%8" OMR_PRIxPTR ":%s%d\n", (uintptr_t)vmThread, msg, entry->_index);11145}1114611147// This method must be called with the Compilation Monitor in hand11148//11149void11150TR::CompilationInfo::printQueue()11151{11152if (!_traceCompiling)11153return;1115411155fprintf(stderr, "\t\t\tActive: ");11156bool activeMethods = false;1115711158for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)11159{11160TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];11161TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");1116211163TR_MethodToBeCompiled * methodBeingCompiled = curCompThreadInfoPT->getMethodBeingCompiled();1116411165if (methodBeingCompiled)11166{11167activeMethods = true;11168fprintf(stderr, "(%4d) %d:", methodBeingCompiled->_numThreadsWaiting, methodBeingCompiled->_index);11169debugPrint(methodBeingCompiled->getMethodDetails().getMethod());11170}11171}11172if (!activeMethods)11173fprintf(stderr, "none");1117411175for (TR_MethodToBeCompiled *p = _methodQueue; p; p = p->_next)11176{11177fprintf(stderr, "\n\t\t\tQueued: (%4d) %d:", p->_numThreadsWaiting, p->_index);11178debugPrint(p->getMethodDetails().getMethod());11179}11180fprintf(stderr, "\n");11181}11182#endif111831118411185TR_HWProfiler *11186TR::CompilationInfo::getHWProfiler() const11187{11188return ((TR_JitPrivateConfig*)_jitConfig->privateConfig)->hwProfiler;11189}1119011191TR_JProfilerThread *11192TR::CompilationInfo::getJProfilerThread() const11193{11194return ((TR_JitPrivateConfig*)_jitConfig->privateConfig)->jProfiler;11195}1119611197int32_t11198TR::CompilationInfo::calculateCodeSize(TR_MethodMetaData *metaData)11199{11200int32_t codeSize = 0;1120111202if (metaData)11203{11204codeSize = ((uint8_t*)metaData->endWarmPC) - (uint8_t*)metaData->startPC;11205if (metaData->startColdPC)11206codeSize += ((uint8_t*)metaData->endPC) - (uint8_t*)metaData->startColdPC;11207}1120811209return codeSize;11210}1121111212void11213TR::CompilationInfo::increaseUnstoredBytes(U_32 aotBytes, U_32 jitBytes)11214{11215#if 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))11216J9SharedClassConfig *scConfig = _jitConfig->javaVM->sharedClassConfig;11217if (scConfig && scConfig->increaseUnstoredBytes)11218scConfig->increaseUnstoredBytes(_jitConfig->javaVM, aotBytes, jitBytes);11219#endif11220}112211122211223uint64_t11224TR::CompilationInfo::computeFreePhysicalMemory(bool &incompleteInfo)11225{11226bool incomplete = false;11227PORT_ACCESS_FROM_JITCONFIG(_jitConfig);1122811229uint64_t freePhysicalMemory = OMRPORT_MEMINFO_NOT_AVAILABLE;11230J9MemoryInfo memInfo;11231if (0 == j9sysinfo_get_memory_info(&memInfo)11232&& memInfo.availPhysical != OMRPORT_MEMINFO_NOT_AVAILABLE11233&& memInfo.hostAvailPhysical != OMRPORT_MEMINFO_NOT_AVAILABLE)11234{11235freePhysicalMemory = memInfo.availPhysical;11236uint64_t freeHostPhysicalMemorySizeB = memInfo.hostAvailPhysical;1123711238if (memInfo.cached != OMRPORT_MEMINFO_NOT_AVAILABLE)11239freePhysicalMemory += memInfo.cached;11240else11241incomplete = !_cgroupMemorySubsystemEnabled;1124211243if (memInfo.hostCached != OMRPORT_MEMINFO_NOT_AVAILABLE)11244freeHostPhysicalMemorySizeB += memInfo.hostCached;11245else11246incomplete = true;11247#if defined(LINUX)11248if (memInfo.buffered != OMRPORT_MEMINFO_NOT_AVAILABLE)11249freePhysicalMemory += memInfo.buffered;11250else11251incomplete = incomplete || !_cgroupMemorySubsystemEnabled;1125211253if (memInfo.hostBuffered != OMRPORT_MEMINFO_NOT_AVAILABLE)11254freeHostPhysicalMemorySizeB += memInfo.hostBuffered;11255else11256incomplete = true;11257#endif11258// If we run in a container, freePhysicalMemory is the difference between11259// the container memory limit and how much physical memory the container used11260// It's possible that on the entire machine there is less physical memory11261// available because other processes have consumed it. Thus, we need to take11262// into account the available physical memory on the host11263if (freeHostPhysicalMemorySizeB < freePhysicalMemory)11264freePhysicalMemory = freeHostPhysicalMemorySizeB;11265}11266else11267{11268incomplete= true;11269freePhysicalMemory = OMRPORT_MEMINFO_NOT_AVAILABLE;11270}1127111272incompleteInfo = incomplete;11273return freePhysicalMemory;11274}112751127611277uint64_t11278TR::CompilationInfo::computeAndCacheFreePhysicalMemory(bool &incompleteInfo, int64_t updatePeriodMs)11279{11280if (updatePeriodMs < 0)11281updatePeriodMs = (int64_t)TR::Options::getUpdateFreeMemoryMinPeriod();11282// If the OS ever gave us bad information, avoid future calls11283if (_cachedFreePhysicalMemoryB != OMRPORT_MEMINFO_NOT_AVAILABLE)11284{11285static int64_t lastUpdateTime = 0;11286int64_t crtElapsedTime = getPersistentInfo()->getElapsedTime();1128711288if (lastUpdateTime == 011289|| (crtElapsedTime - lastUpdateTime) >= updatePeriodMs)11290{11291// time to recompute freePhysicalMemory11292bool incomplete;11293uint64_t freeMem = computeFreePhysicalMemory(incomplete);1129411295// Cache the computed value for future reference11296// Synchronization issues can be ignored here11297_cachedIncompleteFreePhysicalMemory = incomplete;11298_cachedFreePhysicalMemoryB = freeMem;11299lastUpdateTime = crtElapsedTime;11300}11301}11302incompleteInfo = _cachedIncompleteFreePhysicalMemory;11303return _cachedFreePhysicalMemoryB;11304}113051130611307uint64_t11308TR::CompilationInfo::computeFreePhysicalLimitAndAbortCompilationIfLow(TR::Compilation *comp,11309bool &incompleteInfo,11310size_t sizeToAllocate)11311{11312uint64_t freePhysicalMemorySizeB = computeAndCacheFreePhysicalMemory(incompleteInfo);11313if (OMRPORT_MEMINFO_NOT_AVAILABLE != freePhysicalMemorySizeB)11314{11315bool fail = false;11316// Avoid consuming the last drop of physical memory for JIT (leave 50 MB for emergency)11317// TODO: the emergency could be generated from SWAP11318if (freePhysicalMemorySizeB >= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue())11319{11320freePhysicalMemorySizeB -= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue();11321// Fail the compilation now if the remaining physical memory is not enough11322// to perform a warm compilation that may use up to 'sizeToAllocate' memory11323// However, do not fail if information about physical memory is incomplete11324if (!incompleteInfo && freePhysicalMemorySizeB < sizeToAllocate)11325fail = true;11326}11327else11328{11329fail = !incompleteInfo;11330}11331if (fail)11332{11333if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))11334{11335TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, "Aborting Compilation: Low On Physical Memory %lld B", freePhysicalMemorySizeB);11336}1133711338comp->failCompilation<J9::LowPhysicalMemory>("Low Physical Memory");11339}11340}11341return freePhysicalMemorySizeB;11342}1134311344void11345TR::CompilationInfo::replenishInvocationCount(J9Method *method, TR::Compilation *comp)11346{11347// Replenish the counts of the method11348// We are holding the compilation monitor at this point11349J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);11350if (romMethod->modifiers & J9AccNative)// Never change the extra field of a native method11351return;1135211353int32_t methodVMExtra = TR::CompilationInfo::getJ9MethodVMExtra(method);11354if ((methodVMExtra == 1) || (methodVMExtra == J9_JIT_QUEUED_FOR_COMPILATION))11355{11356int32_t count;11357#if defined(J9VM_OPT_JITSERVER)11358// Even if the option to disable AOT relocation delay was specified, we need to delay relocation of deserialized11359// AOT methods using SVM received from the JITServer AOT cache until the next interpreted invocation. Such methods11360// cannot be immediately relocated in the current implementation; see CompilationInfo::canRelocateMethod().11361if (comp->isDeserializedAOTMethodUsingSVM() && comp->getOption(TR_DisableDelayRelocationForAOTCompilations))11362count = 0;11363else11364#endif /* defined(J9VM_OPT_JITSERVER) */11365// We want to use high counts unless the user specified counts on the command line11366// or used useLowerMethodCounts (or -Xquickstart)11367if (TR::Options::getCountsAreProvidedByUser() || (TR::Options::startupTimeMatters() == TR_yes))11368count = getCount(romMethod, comp->getOptions(), comp->getOptions());11369else11370count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;1137111372TR::CompilationInfo::setInvocationCount(method, count);11373if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))11374{11375// compiler must exist because startPC != NULL11376TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Reencoding count=%d for %s j9m=%p ", count, comp->signature(), method);11377}11378}11379else11380{11381TR_ASSERT(false, "Unexpected value for method->extra = %p (method=%p)\n", TR::CompilationInfo::getJ9MethodExtra(method), method);11382}11383}1138411385void11386TR::CompilationInfo::addJ9HookVMDynamicCodeLoadForAOT(J9VMThread* vmThread, J9Method* method, J9JITConfig* jitConfig, TR_MethodMetaData* relocatedMetaData)11387{11388OMR::CodeCacheMethodHeader *ccMethodHeader;11389ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(11390jitConfig->javaVM->hookInterface,11391vmThread,11392method,11393reinterpret_cast<void *>(relocatedMetaData->startPC),11394relocatedMetaData->endWarmPC - relocatedMetaData->startPC,11395"JIT warm body",11396relocatedMetaData11397);11398if (relocatedMetaData->startColdPC)11399{11400// Register the cold code section too11401//11402ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(11403jitConfig->javaVM->hookInterface,11404vmThread,11405method,11406reinterpret_cast<void *>(relocatedMetaData->startColdPC),11407relocatedMetaData->endPC - relocatedMetaData->startColdPC,11408"JIT cold body",11409relocatedMetaData11410);11411}11412ccMethodHeader = getCodeCacheMethodHeader(11413reinterpret_cast<char *>(relocatedMetaData->startPC),1141432,11415relocatedMetaData11416);11417if (ccMethodHeader && (relocatedMetaData->bodyInfo != NULL))11418{11419J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(reinterpret_cast<void *>(relocatedMetaData->startPC));11420if (linkageInfo->isRecompMethodBody())11421{11422ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(11423jitConfig->javaVM->hookInterface,11424vmThread,11425method,11426ccMethodHeader->_eyeCatcher + 4,11427relocatedMetaData->startPC - reinterpret_cast<uintptr_t>(ccMethodHeader->_eyeCatcher + 4),11428"JIT method header",11429relocatedMetaData11430);11431}11432}11433}1143411435#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))11436void11437TR::CompilationInfo::storeAOTInSharedCache(11438J9VMThread *vmThread,11439J9ROMMethod *romMethod,11440const U_8 *dataStart,11441UDATA dataSize,11442const U_8 *codeStart,11443UDATA codeSize,11444TR::Compilation *comp,11445J9JITConfig *jitConfig,11446TR_MethodToBeCompiled *entry11447)11448{11449bool safeToStore;11450const J9JITDataCacheHeader *storedCompiledMethod = NULL;11451PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);11452TR::CompilationInfo *compInfo = TR::CompilationInfo::get();1145311454if (static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_yes)11455{11456safeToStore = true;11457}11458else if (static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_maybe)11459{11460TR_ASSERT_FATAL(static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader != TR_maybe, "Should not be possible for aotValidHeader to be TR_maybe at this point\n");11461}11462else11463{11464safeToStore = false;11465}1146611467if (safeToStore)11468{11469const U_8 *metadataToStore = dataStart;11470const U_8 *codedataToStore = codeStart;11471int metadataToStoreSize = dataSize;11472int codedataToStoreSize = codeSize;1147311474#ifdef COMPRESS_AOT_DATA11475try11476{11477if (!comp->getOption(TR_DisableAOTBytesCompression))11478{11479/**11480* For each compiled method data we store in the shareclass cache looks like following.11481* -----------------------------------------------------------------------------------------------------11482* | CompiledMethodWrapper | J9JITDataCacheHeader | TR_AOTMethodHeader | Metadata | Compiled Code Data |11483* -----------------------------------------------------------------------------------------------------11484*11485* When we compile a method, we send data from J9JITDataCacheHeader to store in the cache.11486* For each method Shared Class Cache API adds CompiledMethodWrapper header which holds the size of data in cache,11487* as well as J9ROMMethod of compiled method.11488* Size of the original data is extracted from the TR_AOTMethodHeader while size of compressed data is extracted from11489* CompiledMethodWrapper.11490* That is why We do not compress header as we can extract the original data size11491* which is useful information while inflating the method data while loading compiled method.11492*11493* Compressed data stored in the cache looks like following11494* ------------------------------------------------------------------------------------------------------------------------------------------------11495* | CompiledMethodWrapper | J9JITDataCacheHeader (UnCompressed)| TR_AOTMethodHeader (UnCompressed)| (Metadata + Compiled Code Data) (Compressed) |11496* ------------------------------------------------------------------------------------------------------------------------------------------------11497*11498*/11499void * originalData = comp->trMemory()->allocateHeapMemory(codeSize+dataSize);11500void * compressedData = comp->trMemory()->allocateHeapMemory(codeSize+dataSize);1150111502// Copy the metadata and codedata combined into single buffer so that we can compress it together11503memcpy(originalData, dataStart, dataSize);11504memcpy((U_8*)(originalData)+dataSize, codeStart, codeSize);11505int aotMethodHeaderSize = sizeof(J9JITDataCacheHeader)+sizeof(TR_AOTMethodHeader);11506int compressedDataSize = deflateBuffer((U_8*)(originalData)+aotMethodHeaderSize, dataSize+codeSize-aotMethodHeaderSize, (U_8*)(compressedData)+aotMethodHeaderSize, Z_DEFAULT_COMPRESSION);11507if (compressedDataSize != COMPRESSION_FAILED)11508{11509/**11510* We are going to store both metadata and code in contiguous memory in shared class cache.11511* In load run we get the whole buffer from the cache and use the information from header to11512* Get the relocation data and compiled code.11513* Because of this reason we copy both metadata and compiled code in one buffer and deflate it together.11514* TODO: We will always query the shared class cache to get full data for stored AOT compiled method11515* that is combined meta data and code data. Even if compression of AOT bytes is disabled, we do not need11516* to send two different buffers to store in cache and also as no one queries either code data / metadata for11517* method, clean up the share classs cache API.11518*/11519const J9JITDataCacheHeader *aotMethodHeader = reinterpret_cast<const J9JITDataCacheHeader *>(dataStart);11520TR_AOTMethodHeader *aotMethodHeaderEntry = const_cast<TR_AOTMethodHeader *>(reinterpret_cast<const TR_AOTMethodHeader *>(aotMethodHeader + 1));1152111522aotMethodHeaderEntry->flags |= TR_AOTMethodHeader_CompressedMethodInCache;11523memcpy(compressedData, dataStart, aotMethodHeaderSize);11524metadataToStore = (const U_8*) compressedData;11525metadataToStoreSize = compressedDataSize+aotMethodHeaderSize;11526codedataToStore = NULL;11527codedataToStoreSize = 0;11528if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))11529{11530TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "%s : Compression of method data Successful - Original method size = %d bytes, Compressed Method Size = %d bytes",11531comp->signature(),11532dataSize+codeSize, metadataToStoreSize);11533}11534}11535else11536{11537if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))11538{11539TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "!%s : Compression of method data Failed - Original method size = %d bytes",11540comp->signature(),11541dataSize+codeSize);11542}11543}11544}11545}11546catch (const std::bad_alloc &allocationFailure)11547{11548// In case we can not allocate extra memory to hold temp data for compressing, we still the uncompressed data into the cache11549if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))11550{11551TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "!%s : Method will not be compressed as necessary memory can not be allocated, Method Size = %d bytes",11552comp->signature(),11553dataSize+codeSize);11554}11555}11556#endif /* COMPRESS_AOT_DATA */1155711558storedCompiledMethod =11559reinterpret_cast<const J9JITDataCacheHeader*>(11560jitConfig->javaVM->sharedClassConfig->storeCompiledMethod(11561vmThread,11562romMethod,11563(const U_8*)metadataToStore,11564metadataToStoreSize,11565(const U_8*)codedataToStore,11566codedataToStoreSize,115670));11568switch(reinterpret_cast<uintptr_t>(storedCompiledMethod))11569{11570case J9SHR_RESOURCE_STORE_FULL:11571{11572if (jitConfig->javaVM->sharedClassConfig->verboseFlags & J9SHR_VERBOSEFLAG_ENABLE_VERBOSE)11573j9nls_printf( PORTLIB, J9NLS_WARNING, J9NLS_RELOCATABLE_CODE_STORE_FULL);11574TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::SHARED_CACHE_FULL);11575disableAOTCompilations();11576}11577break;11578case J9SHR_RESOURCE_STORE_ERROR:11579{11580if (jitConfig->javaVM->sharedClassConfig->verboseFlags & J9SHR_VERBOSEFLAG_ENABLE_VERBOSE)11581j9nls_printf( PORTLIB, J9NLS_WARNING, J9NLS_RELOCATABLE_CODE_STORE_ERROR);11582TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::SHARED_CACHE_STORE_ERROR);11583TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT);11584disableAOTCompilations();11585}11586}11587}11588else11589{11590if (TR::Options::getAOTCmdLineOptions()->getVerboseOption(TR_VerboseCompileEnd))11591{11592PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);11593TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, " Failed AOT cache validation");11594}1159511596disableAOTCompilations();11597}11598}11599#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)) */1160011601//===========================================================11602TR_LowPriorityCompQueue::TR_LowPriorityCompQueue()11603: _firstLPQentry(NULL), _lastLPQentry(NULL), _sizeLPQ(0), _LPQWeight(0),11604_trackingEnabled(false), _spine(NULL), _STAT_compReqQueuedByIProfiler(0), _STAT_conflict(0),11605_STAT_staleScrubbed(0), _STAT_bypass(0), _STAT_compReqQueuedByJIT(0), _STAT_LPQcompFromIprofiler(0),11606_STAT_LPQcompFromInterpreter(0), _STAT_LPQcompUpgrade(0), _STAT_compReqQueuedByInterpreter(0),11607_STAT_numFailedToEnqueueInLPQ(0)11608{11609}1161011611TR_LowPriorityCompQueue::~TR_LowPriorityCompQueue()11612{11613if (_spine)11614jitPersistentFree(_spine);11615}1161611617void TR_LowPriorityCompQueue::startTrackingIProfiledCalls(int32_t threshold)11618{11619if (threshold > 0 && _compInfo->getCpuUtil() && _compInfo->getCpuUtil()->isFunctional()) // Need to have support for CPU utilization11620{11621// Must allocate the cache11622_spine = (Entry*)jitPersistentAlloc(HT_SIZE * sizeof(Entry));11623if (_spine)11624{11625memset(_spine, 0, HT_SIZE * sizeof(Entry));11626_threshold = threshold;11627if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))11628{11629TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Allocated the LPQ tracking hashtable", (uint32_t)_compInfo->getPersistentInfo()->getElapsedTime());11630}11631FLUSH_MEMORY(TR::Compiler->target.isSMP());11632_trackingEnabled = true;11633}11634}11635}1163611637inline11638bool TR_LowPriorityCompQueue::isTrackableMethod(J9Method *j9method) const11639{11640return !TR::CompilationInfo::isCompiled(j9method) && TR::CompilationInfo::getJ9MethodVMExtra(j9method) > 0;11641}1164211643// Search given j9method in the hashtable;11644// If method found, increment counter11645// if counter equals threshold, add compilation request to the "Idle queue"11646void TR_LowPriorityCompQueue::tryToScheduleCompilation(J9VMThread *vmThread, J9Method *j9method)11647{11648// avoid mocking with startup heuristics11649if ((jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP && !TR::Options::getCmdLineOptions()->getOption(TR_EarlyLPQ)) ||11650// generating more compilations when there is plenty of work is counterproductive11651_compInfo->getNumQueuedFirstTimeCompilations() >= TR::Options::_qsziMaxToTrackLowPriComp ||11652// conserve idle time in the long run11653_compInfo->getPersistentInfo()->getElapsedTime() > 3600000 ||11654// Methods that are already compiled or queued for compilation should not be tracked11655!isTrackableMethod(j9method))11656return;1165711658// Find the j9method in the hashtable11659Entry *entry = _spine + TR_LowPriorityCompQueue::hash(j9method);11660if (entry->_j9method == (uintptr_t)j9method) // found match11661{11662if (++entry->_count > _threshold) // hot entry; possibly queue compilation11663{11664if (!entry->_queuedForCompilation)11665{11666// AOT compilations could be delayed in order to accumulate more11667// IProfiler information. For such methods we don't want to accelerate11668// the compilation. Because it is expensive to identify such methods11669// we only do it when we reached the threshold for compilation11670// TODO: can we actually detect first run?11671if (TR::Options::sharedClassCache() && // must have AOT enabled11672!TR::Options::getCmdLineOptions()->getOption(TR_DisableDelayRelocationForAOTCompilations) &&11673!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoLoadAOT))11674{11675TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, vmThread);11676// Invalidate the entry so that another j9method can use it11677if (vmThread->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, fe->getROMMethodFromRAMMethod(j9method)))11678entry->setInvalid();11679}11680else11681{11682// Check that the invocation count has been decremented enough to accumulate11683// some IP info and then queue a low priority compilation request11684// We only look at loopy methods because there is a greater chance11685// they will have the invocation count decremented very little.11686bool enoughIPInfo;11687J9ROMMethod * romMethod = (J9ROMMethod*)J9_ROM_METHOD_FROM_RAM_METHOD(j9method);11688bool isLoopy = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod);11689// Trying to guess the initial invocation count is error prone and adds overhead11690// We must use some quick and dirty solution. Always assume TR_DEFAULT_INITIAL_BCOUNT11691if (isLoopy)11692{11693// For AOT bodies we use scount11694// For bootstrap romMethods present in SCC (but no AOT body) and loaded during startup, use low counts11695// For everybody else use high counts11696int32_t guessedInitialCount = TR::Options::getCountsAreProvidedByUser() ?11697TR::Options::getCmdLineOptions()->getInitialBCount() :11698TR_DEFAULT_INITIAL_BCOUNT;11699int32_t crtInvocationCount = (int32_t)TR::CompilationInfo::getInvocationCount(j9method);11700enoughIPInfo = (crtInvocationCount + TR::Options::_invocationThresholdToTriggerLowPriComp < guessedInitialCount);11701}11702else11703{11704enoughIPInfo = true;11705}11706if (enoughIPInfo)11707{11708entry->_queuedForCompilation = true;1170911710_compInfo->getCompilationMonitor()->enter();11711bool enqueued = addFirstTimeCompReqToLPQ(j9method, TR_MethodToBeCompiled::REASON_IPROFILER_CALLS);11712// If conditions allow for processing of an LPQ request11713// we may have to notify a sleeping thread or activate a new one11714if (enqueued && _compInfo->canProcessLowPriorityRequest())11715{11716if (_compInfo->getNumCompThreadsJobless() > 0)11717{11718_compInfo->getCompilationMonitor()->notifyAll();11719if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))11720{11721TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u LPQ logic waking up a sleeping comp thread. Jobless=%d",11722(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(),11723_compInfo->getNumCompThreadsJobless());11724}11725}11726else // At least one thread is active.11727{11728// Do we need to activate another compilation thread?11729int32_t numCompThreadsSuspended = _compInfo->getNumUsableCompilationThreads() - _compInfo->getNumCompThreadsActive();11730// Do not activate the last suspended thread11731if (numCompThreadsSuspended > 1)11732{11733TR_YesNoMaybe activate = _compInfo->shouldActivateNewCompThread();11734// If the answer is TR_maybe we may have to look at how many11735// threads are allowed to work on LPQ requests11736if (activate == TR_yes ||11737(activate == TR_maybe &&11738TR::Options::getCmdLineOptions()->getOption(TR_ConcurrentLPQ) &&11739jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP && // ConcurrentLPQ is too damaging to startup11740_compInfo->getNumCompThreadsActive() + 2 < _compInfo->getNumTargetCPUs()11741)11742)11743{11744TR::CompilationInfoPerThread *compInfoPT = _compInfo->getFirstSuspendedCompilationThread();11745compInfoPT->resumeCompilationThread();11746if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))11747{11748TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Activate compThread %d to handle LPQ request. Qweight=%d active=%d",11749(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(),11750compInfoPT->getCompThreadId(),11751_compInfo->getQueueWeight(),11752_compInfo->getNumCompThreadsActive());11753}11754}11755}11756}11757}11758_compInfo->getCompilationMonitor()->exit();1175911760if (enqueued)11761{11762if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))11763{11764TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "t=%u Compile request to LPQ for j9m=%p loopy=%d smpl=%u cnt=%d Q_SZ=%d Q_SZI=%d LPQ_SZ=%d CPU=%d%% JVM_CPU=%d%%",11765(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(),11766j9method,11767isLoopy,11768entry->_count,11769(int32_t)TR::CompilationInfo::getInvocationCount(j9method),11770_compInfo->getMethodQueueSize(),11771_compInfo->getNumQueuedFirstTimeCompilations(),11772getLowPriorityQueueSize(),11773_compInfo->getCpuUtil()->getCpuUsage(),11774_compInfo->getCpuUtil()->getVmCpuUsage());11775}11776}11777else // could not generate a comp req, maybe because of OOM11778{11779entry->setInvalid();11780}11781}11782}11783}11784}11785}11786else // no match11787{11788if (entry->isInvalid()) // entry is invalid, so we can reuse it11789{11790entry->initialize(j9method, 1);11791}11792else11793{11794// Scrub for stale entries that hold compiled methods11795// To make sure that entry->_j9method is actually valid we need to purge entries on class unload11796if (!isTrackableMethod((J9Method*)entry->_j9method))11797{11798entry->setInvalid();11799_STAT_staleScrubbed++;11800entry->initialize(j9method, 1);11801}11802else11803{11804_STAT_conflict++;11805// An idea is to push a compilation for the existing entry if it's close to11806// reaching its compilation threshold11807//fprintf(stderr, "Conflict j9method=%p locationID=%u\n", j9method, TR_LowPriorityCompQueue::hash(j9method));11808}11809}11810}11811}118121181311814void TR_LowPriorityCompQueue::stopTrackingMethod(J9Method *j9method)11815{11816Entry *entry = _spine + TR_LowPriorityCompQueue::hash(j9method);11817if (entry->_j9method == (uintptr_t)j9method)11818{11819//TR_ASSERT(entry->_queuedForCompilation, "Entry %p, j9method %p j9m=%p, count=%u queued=%d (should be 1)\n", entry, entry->_j9method, j9method, entry->_count, entry->_queuedForCompilation);11820entry->setInvalid();11821}11822}11823// Bad scenario: put method in LPQ. Method gets compiled normally and entry becomes scrubabble.11824// Then the same method (running interpreted) finds the same entry usable and stores something in there.118251182611827void TR_LowPriorityCompQueue::purgeEntriesOnClassLoaderUnloading(J9ClassLoader *j9classLoader)11828{11829if (isTrackingEnabled())11830{11831TR_ASSERT(_spine, "_spine must non-null once tracking is enabled");11832Entry *endOfHT = _spine + HT_SIZE;11833for (Entry *entry = _spine; entry < endOfHT; entry++)11834{11835if (entry->_j9method && J9_CLASS_FROM_METHOD((J9Method *)entry->_j9method)->classLoader == j9classLoader)11836entry->setInvalid();11837}11838}11839}1184011841void TR_LowPriorityCompQueue::purgeEntriesOnClassRedefinition(J9Class *j9class)11842{11843if (isTrackingEnabled())11844{11845TR_ASSERT(_spine, "_spine must non-null once tracking is enabled");11846Entry *endOfHT = _spine + HT_SIZE;11847for (Entry *entry = _spine; entry < endOfHT; entry++)11848{11849if (entry->_j9method && J9_CLASS_FROM_METHOD((J9Method *)entry->_j9method) == j9class)11850entry->setInvalid();11851}11852}11853}1185411855void TR_LowPriorityCompQueue::incStatsCompFromLPQ(uint8_t reason)11856{11857switch (reason) {11858case TR_MethodToBeCompiled::REASON_IPROFILER_CALLS:11859_STAT_LPQcompFromIprofiler++; break;11860case TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED:11861_STAT_LPQcompFromInterpreter++; break;11862case TR_MethodToBeCompiled::REASON_UPGRADE:11863_STAT_LPQcompUpgrade++; break;11864default:11865TR_ASSERT(false, "No other known reason for LPQ compilations\n");11866}11867}1186811869void TR_LowPriorityCompQueue::incStatsReqQueuedToLPQ(uint8_t reason)11870{11871switch (reason) {11872case TR_MethodToBeCompiled::REASON_IPROFILER_CALLS:11873_STAT_compReqQueuedByIProfiler++; break;11874case TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED:11875_STAT_compReqQueuedByInterpreter++; break;11876case TR_MethodToBeCompiled::REASON_UPGRADE:11877_STAT_compReqQueuedByJIT++; break;11878default:11879TR_ASSERT(false, "No other known reason for LPQ compilations\n");11880}11881}1188211883void TR_LowPriorityCompQueue::printStats() const11884{11885fprintf(stderr, "Stats for LPQ:\n");1188611887fprintf(stderr, " Requests for LPQ = %4u (Sources: IProfiler=%3u Interpreter=%3u JIT=%3u)\n",11888_STAT_compReqQueuedByIProfiler + _STAT_compReqQueuedByInterpreter + _STAT_compReqQueuedByJIT,11889_STAT_compReqQueuedByIProfiler, _STAT_compReqQueuedByInterpreter, _STAT_compReqQueuedByJIT);11890fprintf(stderr, " Comps. from LPQ = %4u (Sources: IProfiler=%3u Interpreter=%3u JIT=%3u)\n",11891_STAT_LPQcompFromIprofiler + _STAT_LPQcompFromInterpreter + _STAT_LPQcompUpgrade,11892_STAT_LPQcompFromIprofiler, _STAT_LPQcompFromInterpreter, _STAT_LPQcompUpgrade);1189311894fprintf(stderr, " Conflicts = %4u (tried to cache j9method that didn't have space)\n", _STAT_conflict);11895fprintf(stderr, " Stale entries = %4u\n", _STAT_staleScrubbed); // we want very few of these, hopefully 011896fprintf(stderr, " Bypass ocurrences= %4u (normal comp req hapened before the fast LPQ comp req)\n", _STAT_bypass);11897}1189811899void TR_LowPriorityCompQueue::invalidateRequestsForUnloadedMethods(J9Class * unloadedClass)11900{11901TR_MethodToBeCompiled *cur = _firstLPQentry;11902TR_MethodToBeCompiled *prev = NULL;11903bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);11904while (cur)11905{11906TR_MethodToBeCompiled *next = cur->_next;11907TR::IlGeneratorMethodDetails & details = cur->getMethodDetails();11908J9Method *method = details.getMethod();11909if (method)11910{11911if (J9_CLASS_FROM_METHOD(method) == unloadedClass ||11912(details.isNewInstanceThunk() &&11913static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))11914{11915TR_ASSERT(cur->_priority < CP_SYNC_MIN,11916"Unloading cannot happen for SYNC requests");11917if (verbose)11918TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Invalidating compile request from LPQ for method=%p class=%p", method, unloadedClass);1191911920// detach from queue11921if (prev)11922prev->_next = cur->_next;11923else11924_firstLPQentry = cur->_next;11925if (cur == _lastLPQentry)11926_lastLPQentry = prev;11927_sizeLPQ--;11928decreaseLPQWeightBy(cur->_weight);1192911930// put back into the pool11931_compInfo->recycleCompilationEntry(cur);11932}11933else11934{11935prev = cur;11936}11937}11938cur = next;11939}11940}1194111942void TR_LowPriorityCompQueue::purgeLPQ()11943{11944while (_firstLPQentry)11945{11946TR_MethodToBeCompiled *cur = _firstLPQentry;11947_firstLPQentry = _firstLPQentry->_next;11948_sizeLPQ--;11949decreaseLPQWeightBy(cur->_weight);11950_compInfo->recycleCompilationEntry(cur);11951}11952_lastLPQentry = NULL;11953}1195411955TR_MethodToBeCompiled * TR_LowPriorityCompQueue::extractFirstLPQRequest()11956{11957// take the top method out of the queue11958TR_MethodToBeCompiled *m = _firstLPQentry;11959_firstLPQentry = _firstLPQentry->_next;11960_sizeLPQ--;11961decreaseLPQWeightBy(m->_weight);11962if (!_firstLPQentry)11963_lastLPQentry = 0;11964return m;11965}1196611967// Searches the entire LPQ queue for an entry with the given method and given "reason"11968// If method is not found we return NULL.11969// If given method is found but the "reason" does not match, the entry is returned11970// and the "dequeued" flag is set to false to indicate that the entry is still part of the LPQ11971// If method is found and the "reason" matches, the entry is detached and returned to the caller11972// while the "dequeued" flag is set to true.11973// Needs compilation queue monitor in hand11974TR_MethodToBeCompiled *11975TR_LowPriorityCompQueue::findAndDequeueFromLPQ(TR::IlGeneratorMethodDetails &details,11976uint8_t reason, TR_J9VMBase *fe, bool & dequeued)11977{11978dequeued = false;11979TR_MethodToBeCompiled *cur = _firstLPQentry, *prev = NULL;11980while (cur)11981{11982if (cur->getMethodDetails().sameAs(details, fe))11983{11984if (cur->_reqFromSecondaryQueue == reason)11985{11986// detach from queue11987if (prev)11988prev->_next = cur->_next;11989else11990_firstLPQentry = cur->_next;11991if (cur == _lastLPQentry)11992_lastLPQentry = prev;11993_sizeLPQ--;11994decreaseLPQWeightBy(cur->_weight);11995dequeued = true;11996break;11997}11998else11999{12000break; // Will return un-detached entry12001}12002}1200312004prev = cur;12005cur = cur->_next;12006}1200712008return cur;12009}1201012011TR_CompilationErrorCode12012TR::CompilationInfo::scheduleLPQAndBumpCount(TR::IlGeneratorMethodDetails &details, TR_J9VMBase *fe)12013{12014J9Method *method = details.getMethod();12015// Search the LPQ and if not found, add method to LPQ and bump invocation count12016// If method is found, move it to main queue12017// We prevent concurrency issues by making sure the invocation count is 0 when adding to LPQ12018// We must make sure that if the method is not found in LPQ there is absolutely no way12019// it can be present in main queue (invocation count being 0 should guarantee us that12020// because a method waiting in main queue should be marked QUEUED_FOR_COMPILATION)12021// We should put an assert that all ordinary async first time compilations in the main12022// queue are marked QUEUED_FOR_COMPILATION12023// To summarize: methods in LPQ can have any invocation count, but methods12024// in main queue must have an invocation count of QUEUED_FOR_COMPILATION12025intptr_t count = getInvocationCount(method);12026if (count == 0)12027{12028bool dequeued = false;12029TR_MethodToBeCompiled *entry = getLowPriorityCompQueue().findAndDequeueFromLPQ(details, TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED, fe, dequeued);12030if (!dequeued) // Early compilation request12031{12032// Place request in LPQ if it doesn't already exist12033bool queued = true;12034if (entry)12035{12036// Change the reason so that when the counter expires again we move the entry to the main queue12037entry->_reqFromSecondaryQueue = TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED;12038}12039else // try to queue12040{12041queued = getLowPriorityCompQueue().addFirstTimeCompReqToLPQ(method, TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED);12042}12043if (queued)12044{12045// We must replenish the invocation count12046J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);12047TR_ASSERT((romMethod->modifiers & J9AccNative) == 0, "Should not change invocation count for natives");1204812049// Decide what value to add12050// TODO: look at options sets1205112052intptr_t newCount = getCount(romMethod, TR::Options::getCmdLineOptions(), TR::Options::getAOTCmdLineOptions());12053newCount = newCount * (100 - TR::Options::_countPercentageForEarlyCompilation) / 100; // TODO: verify we don't have negative numbers12054if (TR::CompilationInfo::setInvocationCount(method, count, newCount))12055{12056if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))12057TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "j9m=%p Enqueued in LPQ. LPQ_SZ=%d. Count-->%d",12058method, getLowPriorityCompQueue().getLowPriorityQueueSize(), (int)newCount);12059return compilationNotNeeded;12060}12061else12062{12063// We couldn't set the count maybe because another thread set it to another value12064// Very unlikely to happen12065// Take the request out from LPQ and move it to main queue12066bool removed;12067TR_MethodToBeCompiled *req = getLowPriorityCompQueue().findAndDequeueFromLPQ(details, TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED, fe, removed);12068if (req && removed)12069{12070recycleCompilationEntry(req); // Put the request back into the pool12071}12072else12073{12074TR_ASSERT(false, "We must have found the entry we just added");12075// TODO: add some stats for this case12076}12077}12078}12079else // Couldn't queue to LPQ12080{12081// We must attempt to put it in the main queue12082getLowPriorityCompQueue().incNumFailuresToEnqueue();12083}12084}12085else // Invocation counter expired for a second time12086{12087// Delete this entry and create another one for main queue12088recycleCompilationEntry(entry); // Put the request back into the pool12089}12090}12091else // count is not 012092{12093// This case can happen if two threads call compileMethod() at about the same time12094// The first thread may put a request in LPQ and increase the count12095// The second thread should just ignore the request.12096// We have to make sure that there is no other part of the code12097// that increases the invocation count12098// Release the compilation lock before returning12099return compilationNotNeeded;12100}1210112102return compilationOK;12103}121041210512106void TR_JitSampleInfo::update(uint64_t crtTime, uint32_t crtGlobalSampleCounter)12107{12108if (crtTime > _timestampOfLastInterval) // avoid races12109{12110// Compute size of last observation interval12111_sizeOfLastInterval = crtTime - _timestampOfLastInterval;12112// Compute nr of samples seen in last observation interval12113uint32_t diffSamples = crtGlobalSampleCounter - _globalSampleCounterInLastInterval;12114// Compute density of samples12115_samplesPerSecondDuringLastInterval = diffSamples * 1000 / _sizeOfLastInterval;12116// Prepare for next interval12117_timestampOfLastInterval = crtTime;12118_globalSampleCounterInLastInterval = crtGlobalSampleCounter;1211912120if (_samplesPerSecondDuringLastInterval > _maxSamplesPerSecond) // update maximum12121{12122_maxSamplesPerSecond = _samplesPerSecondDuringLastInterval;12123// May have to change thresholds12124// For 0-199 samples/sec we want a threshold of 3012125// Anything above that will increase the window by 30 for each extra 400 samples/sec12126uint32_t increaseFactor = 1;12127if (_maxSamplesPerSecond >= TR::Options::_sampleDensityBaseThreshold)12128{12129increaseFactor = 2 + ((_maxSamplesPerSecond - TR::Options::_sampleDensityBaseThreshold) / TR::Options::_sampleDensityIncrementThreshold);12130}12131if (increaseFactor != _increaseFactor)12132{12133// Change the _increasefactor, but watch for overflow on 8 bit (Observation window must fit on 8 bits)12134uint32_t maxIncreaseFactor = 0xff / TR::Options::_sampleInterval;12135if (increaseFactor > maxIncreaseFactor)12136increaseFactor = maxIncreaseFactor;12137_increaseFactor = increaseFactor;12138}12139}12140if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseSampleDensity))12141TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u globalSamplesDensity: %u/%u=%u samples/sec max=%u samples/sec increaseFactor=%u",12142crtTime, diffSamples, _sizeOfLastInterval, _samplesPerSecondDuringLastInterval, _maxSamplesPerSecond, _increaseFactor);12143}12144}121451214612147void TR_InterpreterSamplingTracking::addOrUpdate(J9Method *method, int32_t cnt)12148{12149// get the compilation queue monitor12150OMR::CriticalSection mon(_compInfo->getCompilationMonitor());1215112152// search my method in the container12153TR_MethodCnt *item = _container;12154for (; item; item = item->_next)12155{12156if (item->_method == method)12157{12158item->_skippedCount += cnt; // update the skipped count12159break;12160}12161}12162// If method not in the collection yet, add it now12163if (!item)12164{12165item = new (PERSISTENT_NEW) TR_MethodCnt(method, cnt);12166if (item)12167{12168item->_next = _container;12169_container = item;12170_size++;12171if (_size > _maxElements)12172{12173_maxElements = _size;12174//fprintf(stderr, "Max size=%u\n", _maxElements);12175// _maxElements is about 60 for Liberty startup with no SCC/AOT12176}12177}12178}12179// compilation queue monitor automatically released12180}1218112182int32_t TR_InterpreterSamplingTracking::findAndDelete(J9Method *method)12183{12184int32_t retValue = 0;12185TR_MethodCnt *itemToBeDeleted = NULL;1218612187{ // Open a new context12188// get the compilation queue monitor.12189OMR::CriticalSection mon(_compInfo->getCompilationMonitor());12190TR_MethodCnt *item = _container;12191// search my method in the container12192for (TR_MethodCnt *prev = NULL; item; prev = item, item = item->_next)12193{12194if (item->_method == method)12195{12196// detach12197if (prev)12198prev->_next = item->_next;12199else12200_container = item->_next;12201retValue = item->_skippedCount;12202itemToBeDeleted = item;12203_size--;12204break;12205}12206}12207}12208// If element was found, free the memory12209if (itemToBeDeleted)12210jitPersistentFree(itemToBeDeleted);12211return retValue;12212}122131221412215J9Method_HT::HT_Entry::HT_Entry(J9Method *j9method, uint64_t timestamp)12216:_next(NULL), _j9method(j9method), _count(TR::CompilationInfo::getInvocationCount(j9method)), _seqID(0), _timestamp(timestamp) {}1221712218J9Method_HT::J9Method_HT(TR::PersistentInfo *persistentInfo)12219{12220memset(_spine, 0, HT_SIZE * sizeof(HT_Entry*));12221_persistentInfo = persistentInfo;12222_numEntries = 0;12223}1222412225J9Method_HT::HT_Entry * J9Method_HT::find(J9Method *j9method) const12226{12227// Search DLT_HT for this method12228size_t bucketID = hash(j9method) & MASK;12229HT_Entry *entry = _spine[bucketID];12230for (; entry; entry = entry->_next)12231if (entry->_j9method == j9method)12232break;12233return entry;12234}1223512236// onClassUnloading is executed when all threads are stopped12237// so there are no synchronization issues12238void J9Method_HT::onClassUnloading()12239{12240// Scan the entire DLT_HT and delete entries matching the given classloader12241// Also free invalid entries that have j9method==NULL12242for (size_t bucketID = 0; bucketID < HT_SIZE; bucketID++)12243{12244HT_Entry *entry = _spine[bucketID];12245HT_Entry *prev = NULL;12246while (entry)12247{12248J9Class *clazz = J9_CLASS_FROM_METHOD(entry->_j9method);1224912250// Non-Anon classes will be unloaded with their classloaders, hence the class's classloader will be marked as dead.12251// Anon Classes can be independently unloaded without their classloaders, however their classes are marked as dying.12252if ( J9_ARE_ALL_BITS_SET(clazz->classLoader->gcFlags, J9_GC_CLASS_LOADER_DEAD)12253|| (J9CLASS_FLAGS(clazz) & J9AccClassDying) )12254{12255HT_Entry *removed = NULL;12256if (prev)12257prev->_next = entry->_next;12258else12259_spine[bucketID] = entry->_next;12260removed = entry;12261entry = entry->_next;12262removed->_next = NULL; // for safety12263jitPersistentFree(removed);12264_numEntries--;12265continue;12266}12267prev = entry;12268entry = entry->_next;12269}12270}12271}1227212273bool J9Method_HT::addNewEntry(J9Method *j9method, uint64_t timestamp)12274{12275bool added = false;12276bool alreadyCompiled = TR::CompilationInfo::isCompiled(j9method);1227712278if (_numEntries < 1000 // prevent pathological cases12279&& !alreadyCompiled)12280{12281size_t bucketID = hash(j9method) & MASK;12282HT_Entry * newEntry = new (PERSISTENT_NEW) HT_Entry(j9method, timestamp);12283if (newEntry) // test for OOM12284{12285newEntry->_next = _spine[bucketID];12286if (newEntry->_count < 0)12287newEntry->_count = 0;12288FLUSH_MEMORY(TR::Compiler->target.isSMP());12289_spine[bucketID] = newEntry;12290_numEntries++; // benign multithreading issue12291added = true;12292}12293}12294if (TR::Options::getVerboseOption(TR_VerboseSampling))12295TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u J9MethodTracking: j9m=%p Adding new entry. compiled:%d success=%d totalEntries=%u",12296(unsigned)getPersistentInfo()->getElapsedTime(), j9method, alreadyCompiled, added, _numEntries);12297return added;12298}1229912300bool DLTTracking::shouldIssueDLTCompilation(J9Method *j9method, int32_t numHitsInDLTBuffer)12301{12302bool shouldIssueDLT = false;12303int32_t methodCount = TR::CompilationInfo::getInvocationCount(j9method);12304if (methodCount <= 0 || numHitsInDLTBuffer >= TR::Options::_numDLTBufferMatchesToEagerlyIssueCompReq)12305{12306if (TR::Options::getVerboseOption(TR_VerboseSampling))12307TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p Issue DLT because methodCount=%d numHitsInDLTBuffer=%d",12308(unsigned)getPersistentInfo()->getElapsedTime(), j9method, methodCount, numHitsInDLTBuffer);12309return true;12310}12311// Search DLT_HT for this method12312HT_Entry *entry = find(j9method);1231312314if (entry) // if method already exists in DLT_HT12315{12316// If the method's invocation count is the same as the one in the12317// entry, the thread could be stuck in this body. If we encounter12318// this situation several times in succession, we must issue a DLT request12319int32_t entryCount = entry->_count;1232012321if (entryCount == methodCount)12322{12323entry->_seqID += 1;12324if (entry->_seqID >= TR::Options::_dltPostponeThreshold)12325{12326shouldIssueDLT = true;12327// TODO: should we invalidate this entry?12328}12329}12330else12331{12332// If the invocation count has shrunk since the last inspection12333// we must avoid issuing a DLT request because it's possible that12334// some threads have actually left the method (they are not stuck)12335if (methodCount < entryCount)12336{12337// Update the entry count with the invocation count seen when we last checked for DLT12338// Use a CAS construct get around synchronization issues12339int32_t oldValue;12340int32_t newValue;12341do {12342oldValue = entry->_count;12343newValue = TR::CompilationInfo::getInvocationCount(j9method);12344if (newValue < 0)12345newValue = 0;12346} while (oldValue != VM_AtomicSupport::lockCompareExchangeU32((uint32_t*)&entry->_count, oldValue, newValue));1234712348entry->_seqID = 0; // should we reset this?12349}12350}12351if (TR::Options::getVerboseOption(TR_VerboseSampling))12352TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p issueDLT=%d entry=%p entryCount=%d methodCount=%d seqID=%d",12353(unsigned)getPersistentInfo()->getElapsedTime(), j9method, shouldIssueDLT, entry, entryCount, methodCount, entry->_seqID);12354}12355else // method does not exist in DLT_HT12356{12357// Add method to DLT_HT12358// If adding is successful, do not issue DLT request12359shouldIssueDLT = !addNewEntry(j9method, getPersistentInfo()->getElapsedTime());12360if (TR::Options::getVerboseOption(TR_VerboseSampling))12361TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p issueDLT=%d entry=%p",12362(unsigned)getPersistentInfo()->getElapsedTime(), j9method, shouldIssueDLT, entry);12363}1236412365return shouldIssueDLT;12366}12367123681236912370void DLTTracking::adjustStoredCounterForMethod(J9Method *j9method, int32_t countDiff)12371{12372// Search DLT_HT for this method12373HT_Entry *entry = find(j9method);12374if (entry)12375{12376// Subtract from the stored count the value given by the second parameter12377// Use a CAS construct to get around synchronization issues12378int32_t oldValue;12379int32_t newValue;12380do {12381oldValue = entry->_count;12382newValue = oldValue - countDiff;12383if (newValue < 0)12384newValue = 0;12385} while (oldValue != VM_AtomicSupport::lockCompareExchangeU32((uint32_t*)&entry->_count, oldValue, newValue));12386if (TR::Options::getVerboseOption(TR_VerboseSampling))12387TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p entry=%p adjusting entry count to %d",12388(unsigned)getPersistentInfo()->getElapsedTime(), j9method, entry, newValue);12389}12390}12391123921239312394// Must have compMonitor in hand12395void TR_JProfilingQueue::enqueueCompReq(TR_MethodToBeCompiled *compReq)12396{12397// add at the end of queue12398if (_lastQentry)12399_lastQentry->_next = compReq;12400else12401_firstQentry = compReq;1240212403_lastQentry = compReq;12404_size++;12405increaseQWeightBy(compReq->_weight);12406}1240712408// Must have compMonitor in hand12409TR_MethodToBeCompiled *TR_JProfilingQueue::extractFirstCompRequest()12410{12411// take the top method out of the queue12412TR_MethodToBeCompiled *m = _firstQentry;12413_firstQentry = _firstQentry->_next;12414if (!_firstQentry)12415_lastQentry = NULL;12416_size--;12417decreaseQWeightBy(m->_weight);12418return m;12419}1242012421// Must have compMonitor in hand12422bool TR_JProfilingQueue::createCompReqAndQueueIt(TR::IlGeneratorMethodDetails &details, void *startPC)12423{12424TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(warm); // TODO: pick first opt level12425if (!plan)12426return false; // OOM1242712428TR_MethodToBeCompiled * compReq = _compInfo->getCompilationQueueEntry();12429if (!compReq)12430{12431TR_OptimizationPlan::freeOptimizationPlan(plan);12432return false; // OOM12433}12434compReq->initialize(details, 0, CP_ASYNC_ABOVE_MIN, plan);12435compReq->_reqFromJProfilingQueue = true;12436compReq->_jitStateWhenQueued = _compInfo->getPersistentInfo()->getJitState();12437compReq->_oldStartPC = startPC;12438compReq->_async = true; // app threads are not waiting for it1243912440// Determine entry weight12441J9Method *j9method = details.getMethod();12442J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(j9method);12443compReq->_weight = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod)) ? TR::CompilationInfo::WARM_LOOPY_WEIGHT : TR::CompilationInfo::WARM_LOOPLESS_WEIGHT;12444// add at the end of queue12445enqueueCompReq(compReq);12446if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))12447TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "t=%u j9m=%p enqueued in JPQ. JPQ_SZ=%d",12448(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(), j9method, getQSize());1244912450//incStatsReqQueuedToLPQ(reason);12451return true;12452}1245312454bool TR_JProfilingQueue::isJProfilingCandidate(TR_MethodToBeCompiled *entry, TR::Options *options, TR_J9VMBase* fej9)12455{12456if (!options->getOption(TR_EnableJProfiling) ||12457entry->isJNINative() ||12458entry->_oldStartPC != 0 || // reject non first time compilations12459!entry->getMethodDetails().isOrdinaryMethod() ||12460entry->_optimizationPlan->insertInstrumentation() ||12461!options->canJITCompile() ||12462options->getOption(TR_NoRecompile) ||12463!options->allowRecompilation())12464return false;1246512466static char *disableFilterOnJProfiling = feGetEnv("TR_DisableFilterOnJProfiling");12467if (!disableFilterOnJProfiling &&12468!fej9->isClassLibraryMethod((TR_OpaqueMethodBlock *)entry->getMethodDetails().getMethod(), true))12469return false;1247012471return true;12472}1247312474// Must have compMonitor in hand12475void TR_JProfilingQueue::invalidateRequestsForUnloadedMethods(J9Class * unloadedClass)12476{12477TR_MethodToBeCompiled *cur = _firstQentry;12478TR_MethodToBeCompiled *prev = NULL;12479bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);12480while (cur)12481{12482TR_MethodToBeCompiled *next = cur->_next;12483TR::IlGeneratorMethodDetails & details = cur->getMethodDetails();12484J9Method *method = details.getMethod();12485if (method)12486{12487if (J9_CLASS_FROM_METHOD(method) == unloadedClass ||12488(details.isNewInstanceThunk() &&12489static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))12490{12491TR_ASSERT(cur->_priority < CP_SYNC_MIN,12492"Unloading cannot happen for SYNC requests");12493if (verbose)12494TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Invalidating compile request from JPQ for method=%p class=%p", method, unloadedClass);1249512496// detach from queue12497if (prev)12498prev->_next = cur->_next;12499else12500_firstQentry = cur->_next;12501if (cur == _lastQentry)12502_lastQentry = prev;12503_size--;12504decreaseQWeightBy(cur->_weight);1250512506// put back into the pool12507_compInfo->recycleCompilationEntry(cur);12508}12509else12510{12511prev = cur;12512}12513}12514cur = next;12515}12516}1251712518// Must have compMonitor in hand12519void TR_JProfilingQueue::purge()12520{12521while (_firstQentry)12522{12523TR_MethodToBeCompiled *cur = _firstQentry;12524_firstQentry = _firstQentry->_next;12525_size--;12526decreaseQWeightBy(cur->_weight);12527_compInfo->recycleCompilationEntry(cur);12528}12529_lastQentry = NULL;12530}125311253212533// This method returns true when the JIT thinks it's a good12534// time to allow the generation of JProfiling bodies12535bool TR::CompilationInfo::canProcessJProfilingRequest()12536{12537// Once we allow the generation of JProfiling bodies12538// we will not go back12539if (getJProfilingCompQueue().getAllowProcessing())12540{12541return true;12542}12543else12544{12545// Prevent processing during JVM startup or JIT startp/rampup state12546if (_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP ||12547getPersistentInfo()->getJitState() == STARTUP_STATE ||12548getPersistentInfo()->getJitState() == RAMPUP_STATE)12549return false;12550// A sufficiently large number of samples in jitted code must have been seen.12551// This means that the jitted code has run for a while12552if (TR::Recompilation::globalSampleCount < TR::Options::_jProfilingEnablementSampleThreshold)12553{12554return false;12555}12556getJProfilingCompQueue().setAllowProcessing();12557if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))12558{12559TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Allowing generation of JProfiling bodies",12560(uint32_t)getPersistentInfo()->getElapsedTime());12561}12562return true;12563}12564}1256512566bool12567TR::CompilationInfo::canRelocateMethod(TR::Compilation *comp)12568{12569// Delay relocation by default, unless this option is enabled12570if (!comp->getOption(TR_DisableDelayRelocationForAOTCompilations))12571return false;1257212573#if defined(J9VM_OPT_JITSERVER)12574// Delay relocation if this is a deserialized AOT method using SVM received from the JITServer AOT cache.12575// Such methods cannot be immediately relocated in the current implementation. An immediate AOT+SVM load12576// uses the ID-symbol mapping created during compilation. This mapping is missing when the client receives12577// a serialized AOT method from the server, and trying to load the deserialized method immediately12578// triggers fatal assertions in SVM validation in certain cases. As a workaround, we delay the AOT load12579// until the next interpreted invocation of the method; see CompilationInfo::replenishInvocationCounter().12580//12581//TODO: Avoid the overhead of rescheduling this compilation request by handling the deserialized AOT load as if12582// the method came from the local SCC, rather than as if it was freshly AOT-compiled at the JITServer.12583if (comp->isDeserializedAOTMethodUsingSVM())12584return false;12585#endif /* defined(J9VM_OPT_JITSERVER) */1258612587TR_Debug *debug = TR::Options::getDebug();12588TR_FilterBST *filter = NULL;12589return debug ? debug->methodSigCanBeRelocated(comp->signature(), filter) : true;12590}1259112592#if defined(J9VM_OPT_JITSERVER)12593// This method is executed by the JITServer to queue a placeholder for12594// a compilation request received from the client. At the time the new12595// entry is queued we do not know any details about the compilation request.12596// The method needs to be executed with compilation monitor in hand.12597TR_MethodToBeCompiled *12598TR::CompilationInfo::addOutOfProcessMethodToBeCompiled(JITServer::ServerStream *stream)12599{12600TR_MethodToBeCompiled *entry = getCompilationQueueEntry(); // Allocate a new entry12601if (entry)12602{12603// Initialize the entry with defaults (some, like methodDetails, are bogus)12604TR::IlGeneratorMethodDetails details;12605entry->initialize(details, NULL, CP_SYNC_NORMAL, NULL);12606entry->_entryTime = getPersistentInfo()->getElapsedTime(); // Cheaper version12607entry->_stream = stream; // Add the stream to the entry12608incrementMethodQueueSize(); // One more method added to the queue12609_numQueuedFirstTimeCompilations++; // Otherwise an assert triggers when we dequeue12610queueEntry(entry);1261112612// Determine whether we need to activate another compilation thread from the pool12613TR_YesNoMaybe activate = TR_maybe;12614if (getNumCompThreadsActive() <= 0)12615{12616activate = TR_yes;12617}12618else if (getNumCompThreadsJobless() > 0)12619{12620activate = TR_no; // Just wake the jobless one12621}12622else12623{12624int32_t numCompThreadsSuspended = getNumUsableCompilationThreads() - getNumCompThreadsActive();12625TR_ASSERT(numCompThreadsSuspended >= 0, "Accounting error for suspendedCompThreads usable=%d active=%d\n",12626getNumUsableCompilationThreads(), getNumCompThreadsActive());12627// Cannot activate if there is nothing to activate12628activate = (numCompThreadsSuspended <= 0) ? TR_no : TR_yes;12629}1263012631if (activate == TR_yes)12632{12633// Must find one that is SUSPENDED/SUSPENDING12634TR::CompilationInfoPerThread *compInfoPT = getFirstSuspendedCompilationThread();12635if (compInfoPT)12636{12637compInfoPT->resumeCompilationThread();12638if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))12639{12640TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Activate compThread %d Qweight=%d active=%d",12641(uint32_t)getPersistentInfo()->getElapsedTime(), compInfoPT->getCompThreadId(), getQueueWeight(), getNumCompThreadsActive());12642}12643}12644}12645}12646return entry;12647}1264812649void12650TR::CompilationInfo::requeueOutOfProcessEntry(TR_MethodToBeCompiled *entry)12651{12652TR_ASSERT(getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER, "Should be called in JITServer server mode only");1265312654recycleCompilationEntry(entry);1265512656if (entry->_stream && addOutOfProcessMethodToBeCompiled(entry->_stream))12657{12658// successfully queued the new entry, so notify a thread12659getCompilationMonitor()->notifyAll();12660}12661}12662#endif /* defined(J9VM_OPT_JITSERVER) */126631266412665