Path: blob/master/runtime/compiler/control/JitDump.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2020, 2022 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "control/JitDump.hpp"2324#include "codegen/CodeGenerator.hpp"25#include "env/VMJ9.h"26#include "control/MethodToBeCompiled.hpp"27#include "control/CompilationRuntime.hpp"28#include "control/CompilationThread.hpp"29#include "env/ut_j9jit.h"30#include "env/VMAccessCriticalSection.hpp"31#include "ilgen/J9ByteCodeIlGenerator.hpp"32#include "nls/j9dmpnls.h"33#if defined(J9VM_OPT_JITSERVER)34#include "control/JITServerCompilationThread.hpp"35#include "control/JITServerHelpers.hpp"36#include "runtime/JITServerAOTCache.hpp"37#include "runtime/JITServerAOTDeserializer.hpp"38#include "runtime/JITServerIProfiler.hpp"39#include "runtime/JITServerStatisticsThread.hpp"40#include "runtime/Listener.hpp"41#if defined(LINUX)42#include <malloc.h> // for malloc_stats() (Linux glibc only)43#endif /* defined(LINUX) */44#endif /* defined(J9VM_OPT_JITSERVER) */454647struct ILOfCrashedThreadParamenters48{49ILOfCrashedThreadParamenters(J9VMThread *vmThread, TR::Compilation *comp, TR::FILE *jitdumpFile)50: vmThread(vmThread), comp(comp), jitdumpFile(jitdumpFile)51{}5253/// The JVM thread backing the crashed thread54J9VMThread *vmThread;5556/// The compilation object extracted from the crashed thread57TR::Compilation *comp;5859/// The jitdump file to trace the IL of the crashed thread to60TR::FILE *jitdumpFile;61};6263static uintptr_t64traceILOfCrashedThreadProtected(struct J9PortLibrary *portLib, void *handler_arg)65{66auto p = *static_cast<ILOfCrashedThreadParamenters*>(handler_arg);6768TR_J9ByteCodeIlGenerator bci(p.comp->ilGenRequest().details(), p.comp->getMethodSymbol(),69TR_J9VMBase::get(p.vmThread->javaVM->jitConfig, p.vmThread), p.comp, p.comp->getSymRefTab());70bci.printByteCodes();7172// This call will reset the previously recorded symbol reference size to 0, thus indicating to the debug object that73// we should print all the symbol references in the symbol reference table when tracing the trees. By default the74// debug object will only print new symbol references since the last time they were printed. Here we are in a75// crashed thread state so we can safely reset this coutner so we print all the symbol references.76p.comp->setPrevSymRefTabSize(0);77p.comp->dumpMethodTrees("Trees");7879if ((p.vmThread->omrVMThread->vmState & J9VMSTATE_JIT_CODEGEN) == J9VMSTATE_JIT_CODEGEN)80{81TR_Debug *debug = p.comp->getDebug();82debug->dumpMethodInstrs(p.jitdumpFile, "Post Binary Instructions", false, true);83debug->print(p.jitdumpFile, p.comp->cg()->getSnippetList());84debug->dumpMixedModeDisassembly();85}86else if ((p.vmThread->omrVMThread->vmState & J9VMSTATE_JIT_OPTIMIZER) == J9VMSTATE_JIT_OPTIMIZER)87{88// Tree verification is only valid during optimizations as it relies on consistent node counts which are only89// valid before codegen, since the codegen will decrement the node counts as part of instruction selection90p.comp->verifyTrees();91p.comp->verifyBlocks();92}9394return 0;95}9697static void98traceILOfCrashedThread(J9VMThread *vmThread, TR::Compilation *comp, TR::FILE *jitdumpFile)99{100PORT_ACCESS_FROM_VMC(vmThread);101j9nls_printf(PORTLIB, J9NLS_INFO | J9NLS_STDERR, J9NLS_DMP_JIT_TRACE_IL_CRASHED_THREAD);102103bool alreadyHaveVMAccess = ((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) != 0);104bool haveAcquiredVMAccess = false;105if (!alreadyHaveVMAccess)106{107if (0 == vmThread->javaVM->internalVMFunctions->internalTryAcquireVMAccessWithMask(vmThread, J9_PUBLIC_FLAGS_HALT_THREAD_ANY_NO_JAVA_SUSPEND))108{109haveAcquiredVMAccess = true;110}111}112113comp->setOutFile(jitdumpFile);114115TR_Debug *debug = comp->findOrCreateDebug();116debug->setFile(jitdumpFile);117118TR::Options *options = comp->getOptions();119options->setOption(TR_TraceAll);120options->setOption(TR_TraceKnownObjectGraph);121122trfprintf(jitdumpFile, "<ilOfCrashedThread>\n");123124ILOfCrashedThreadParamenters p(vmThread, comp, jitdumpFile);125126U_32 flags = J9PORT_SIG_FLAG_MAY_RETURN |127J9PORT_SIG_FLAG_SIGSEGV | J9PORT_SIG_FLAG_SIGFPE |128J9PORT_SIG_FLAG_SIGILL | J9PORT_SIG_FLAG_SIGBUS | J9PORT_SIG_FLAG_SIGTRAP;129130uintptr_t result = 0;131j9sig_protect(traceILOfCrashedThreadProtected, static_cast<void *>(&p),132jitDumpSignalHandler,133vmThread, flags, &result);134135trfprintf(jitdumpFile, "</ilOfCrashedThread>\n");136137if (!alreadyHaveVMAccess && haveAcquiredVMAccess)138{139vmThread->javaVM->internalVMFunctions->internalReleaseVMAccess(vmThread);140}141}142143static void144jitDumpRecompileWithTracing(J9VMThread *vmThread, J9Method *ramMethod, TR::CompilationInfo *compInfo, TR_Hotness optLevel, bool isProfilingCompile, TR::Options *optionsFromOriginalCompile, bool isAOTBody, void *oldStartPC, TR::FILE *jitdumpFile)145{146PORT_ACCESS_FROM_VMC(vmThread);147J9Class *clazz;148J9ROMMethod *romMethod;149J9UTF8 *methName, *methSig, *className;150#if defined(J9VM_OPT_JITSERVER)151if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)152{153TR_J9VMBase *fej9 = reinterpret_cast<TR_J9VMBase *>(TR_J9VMBase::get(compInfo->getJITConfig(), vmThread, TR_J9VMBase::J9_SERVER_VM));154if (!fej9->vmThreadIsCompilationThread())155{156trfprintf(jitdumpFile, "JitDump for a non-compilation thread on JITServer is not supported.\n");157return;158}159160clazz = reinterpret_cast<J9Class *>(fej9->getClassOfMethod(reinterpret_cast<TR_OpaqueMethodBlock *>(ramMethod)));161romMethod = JITServerHelpers::romMethodOfRamMethod(ramMethod);162methName = J9ROMMETHOD_NAME(romMethod);163methSig = J9ROMMETHOD_SIGNATURE(romMethod);164className = J9ROMCLASS_CLASSNAME(TR::Compiler->cls.romClassOf(reinterpret_cast<TR_OpaqueClassBlock *>(clazz)));165}166else167#endif168{169clazz = J9_CLASS_FROM_METHOD(ramMethod);170romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(ramMethod);171methName = J9ROMMETHOD_NAME(romMethod);172methSig = J9ROMMETHOD_SIGNATURE(romMethod);173className = J9ROMCLASS_CLASSNAME(clazz->romClass);174}175176j9nls_printf(PORTLIB, J9NLS_INFO | J9NLS_STDERR, J9NLS_DMP_JIT_RECOMPILING_METHOD,177(UDATA)J9UTF8_LENGTH(className), J9UTF8_DATA(className),178(UDATA)J9UTF8_LENGTH(methName), J9UTF8_DATA(methName),179(UDATA)J9UTF8_LENGTH(methSig), J9UTF8_DATA(methSig));180181Trc_JIT_DumpCompilingMethod(vmThread, ramMethod, optLevel, oldStartPC);182183// The request to use a trace log gets passed to the compilation via the optimization plan. The options object184// created before the compile is issued will use the trace log we provide to initialize IL tracing.185TR_OptimizationPlan *plan = NULL;186#if defined(J9VM_OPT_JITSERVER)187// JITServer will create a new optimization plan on the client188if (compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER)189#endif190{191plan = TR_OptimizationPlan::alloc(optLevel);192if (NULL == plan)193{194j9nls_printf(PORTLIB, J9NLS_INFO | J9NLS_STDERR, J9NLS_DMP_JIT_OPTIMIZATION_PLAN);195return;196}197198plan->setInsertInstrumentation(isProfilingCompile);199plan->setLogCompilation(jitdumpFile);200}201202trfprintf(jitdumpFile, "<recompilation>\n");203204// Set the VM state of the crashed thread so the diagnostic thread can use consume it205compInfo->setVMStateOfCrashedThread(vmThread->omrVMThread->vmState);206207J9::JitDumpMethodDetails details(ramMethod, optionsFromOriginalCompile, isAOTBody);208auto queued = false;209auto rc = compilationOK;210#if defined(J9VM_OPT_JITSERVER)211if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)212{213// Inform the client that the compilation thread has crashed and send it214// a pointer to the JitDump file, so that it can request215// a JitDump recompilation from the server with an updated plan and method details.216TR_MethodToBeCompiled *entry = TR::compInfoPT->getMethodBeingCompiled();217JITServer::ServerStream *stream = entry->_stream;218stream->write(JITServer::MessageType::compilationThreadCrashed, jitdumpFile);219stream->read<JITServer::Void>();220{221// Add an entry to the compilation queue using the current stream,222// and immediatelly set its method details as JitDump method details,223// so that only the diagnostic thread can compile it.224OMR::CriticalSection compilationMonitorLock(compInfo->getCompilationMonitor());225226compInfo->requeueOutOfProcessEntry(entry);227entry->_methodDetails = TR::IlGeneratorMethodDetails::clone(entry->_methodDetailsStorage, details);228queued = true;229}230// Wait for the recompilation to finish231entry->acquireSlotMonitor(vmThread);232entry->getMonitor()->wait();233entry->releaseSlotMonitor(vmThread);234}235else236#endif237{238compInfo->compileMethod(vmThread, details, oldStartPC, TR_no, &rc, &queued, plan);239}240241trfprintf(jitdumpFile, "</recompilation rc=%d queued=%d>\n", rc, queued);242243if (!queued244#if defined(J9VM_OPT_JITSERVER)245&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER246#endif247)248{249TR_OptimizationPlan::freeOptimizationPlan(plan);250}251}252253uintptr_t254jitDumpSignalHandler(struct J9PortLibrary *portLibrary, uint32_t gpType, void *gpInfo, void *handler_arg)255{256PORT_ACCESS_FROM_VMC(reinterpret_cast<J9VMThread*>(handler_arg));257j9nls_printf(PORTLIB, J9NLS_INFO | J9NLS_STDERR, J9NLS_DMP_JIT_RECURSIVE_CRASH);258return J9PORT_SIG_EXCEPTION_RETURN;259}260261static UDATA262jitDumpStackFrameIterator(J9VMThread *currentThread, J9StackWalkState *walkState)263{264Trc_JIT_DumpWalkingFrame(currentThread);265266if (NULL != walkState->jitInfo)267{268auto *bodyInfo = reinterpret_cast<TR_PersistentJittedBodyInfo *>(walkState->jitInfo->bodyInfo);269if (NULL != bodyInfo)270{271jitDumpRecompileWithTracing(272currentThread,273walkState->method,274reinterpret_cast<TR::CompilationInfo*>(walkState->userData1),275bodyInfo->getHotness(),276bodyInfo->getIsProfilingBody(),277NULL,278bodyInfo->getIsAotedBody(),279bodyInfo->getStartPCAfterPreviousCompile(),280reinterpret_cast<TR::FILE*>(walkState->userData2)281);282}283}284285return J9_STACKWALK_KEEP_ITERATING;286}287288omr_error_t289runJitdump(char *label, J9RASdumpContext *context, J9RASdumpAgent *agent)290{291PORT_ACCESS_FROM_VMC(context);292293J9VMThread *crashedThread = context->javaVM->internalVMFunctions->currentVMThread(context->javaVM);294Trc_JIT_DumpStart(crashedThread);295296#if defined(J9VM_OPT_JITSERVER)297if (context && context->javaVM && context->javaVM->jitConfig)298{299J9JITConfig *jitConfig = context->javaVM->jitConfig;300TR::CompilationInfo *compInfo = TR::CompilationInfo::get(context->javaVM->jitConfig);301if (compInfo)302{303static char *isPrintJITServerMsgStats = feGetEnv("TR_PrintJITServerMsgStats");304if (isPrintJITServerMsgStats)305JITServerHelpers::printJITServerMsgStats(jitConfig, compInfo);306307static char *isPrintJITServerCHTableStats = feGetEnv("TR_PrintJITServerCHTableStats");308if (isPrintJITServerCHTableStats)309JITServerHelpers::printJITServerCHTableStats(jitConfig, compInfo);310311static char *isPrintJITServerIPMsgStats = feGetEnv("TR_PrintJITServerIPMsgStats");312if (isPrintJITServerIPMsgStats)313{314if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)315{316TR_J9VMBase *vmj9 = (TR_J9VMBase *)TR_J9VMBase::get(context->javaVM->jitConfig, NULL);317JITServerIProfiler *iProfiler = (JITServerIProfiler *)vmj9->getIProfiler();318iProfiler->printStats();319}320}321322static char *isPrintJITServerAOTCacheStats = feGetEnv("TR_PrintJITServerAOTCacheStats");323if (isPrintJITServerAOTCacheStats)324{325if (auto aotCacheMap = compInfo->getJITServerAOTCacheMap())326aotCacheMap->printStats(stderr);327if (auto deserializer = compInfo->getJITServerAOTDeserializer())328deserializer->printStats(stderr);329}330331#if defined(LINUX)332static char *isPrintJITServerMallocStats = feGetEnv("TR_PrintJITServerMallocStats");333if (isPrintJITServerMallocStats)334malloc_stats();335#endif /* defined(LINUX) */336}337}338#endif /* defined(J9VM_OPT_JITSERVER) */339340char *crashedThreadName = getOMRVMThreadName(crashedThread->omrVMThread);341j9nls_printf(PORTLIB, J9NLS_INFO | J9NLS_STDERR, J9NLS_DMP_OCCURRED_THREAD_NAME_ID, "JIT", crashedThreadName, crashedThread);342releaseOMRVMThreadName(crashedThread->omrVMThread);343344J9JITConfig *jitConfig = crashedThread->javaVM->jitConfig;345if (NULL == jitConfig)346{347j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_ERROR_IN_DUMP_STR, "JIT", "Could not locate J9JITConfig");348return OMR_ERROR_INTERNAL;349}350351TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);352if (NULL == compInfo)353{354j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_ERROR_IN_DUMP_STR, "JIT", "Could not locate TR::CompilationInfo");355return OMR_ERROR_INTERNAL;356}357358TR_J9VMBase *frontendOfThread = TR_J9VMBase::get(jitConfig, crashedThread);359if (NULL == frontendOfThread)360{361j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_ERROR_IN_DUMP_STR, "JIT", "Could not locate TR_J9VMBase");362return OMR_ERROR_INTERNAL;363}364365TR::Options *options = TR::Options::getCmdLineOptions();366if (NULL == options)367{368j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_ERROR_IN_DUMP_STR, "JIT", "Could not locate TR::Options");369return OMR_ERROR_INTERNAL;370}371372// To avoid a deadlock, release compilation monitor until we are no longer holding it373while (compInfo->getCompilationMonitor()->owned_by_self())374{375compInfo->releaseCompMonitor(crashedThread);376}377378// Release other monitors as well. In particular CHTable and classUnloadMonitor must not be held.379while (TR::MonitorTable::get()->getClassTableMutex()->owned_by_self())380{381frontendOfThread->releaseClassTableMutex(false);382}383384TR::CompilationInfoPerThread *threadCompInfo = compInfo->getCompInfoForThread(crashedThread);385if (NULL != threadCompInfo)386{387TR_MethodToBeCompiled *methodBeingCompiled = threadCompInfo->getMethodBeingCompiled();388389// If we are currently compiling a method, wake everyone waiting for it to compile390if (NULL != methodBeingCompiled && NULL != methodBeingCompiled->getMonitor())391{392methodBeingCompiled->getMonitor()->enter();393methodBeingCompiled->getMonitor()->notifyAll();394methodBeingCompiled->getMonitor()->exit();395396j9nls_printf(PORTLIB, J9NLS_INFO | J9NLS_STDERR, J9NLS_DMP_JIT_NOTIFIED_WAITING_THREADS);397}398399#if defined(J9VM_OPT_JITSERVER)400if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)401{402// Release the class unload RW mutex403auto serverCompInfo = static_cast<TR::CompilationInfoPerThreadRemote *>(threadCompInfo);404while (serverCompInfo->getClassUnloadReadMutexDepth() > 0)405{406serverCompInfo->getClientData()->readReleaseClassUnloadRWMutex(serverCompInfo);407}408}409#endif410411// Release the class unload RW mutex412while (TR::MonitorTable::get()->getClassUnloadMonitorHoldCount(threadCompInfo->getCompThreadId()) > 0)413{414TR::MonitorTable::get()->readReleaseClassUnloadMonitor(threadCompInfo->getCompThreadId());415}416}417418TR::CompilationInfoPerThread *recompilationThreadInfo = compInfo->getCompilationInfoForDiagnosticThread();419if (NULL == recompilationThreadInfo)420{421j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_ERROR_IN_DUMP_STR, "JIT", "Could not locate the diagnostic thread info");422return OMR_ERROR_INTERNAL;423}424425auto *recompilationThread = recompilationThreadInfo->getCompilationThread();426if (NULL == recompilationThread)427{428j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_ERROR_IN_DUMP_STR, "JIT", "Could not locate the diagnostic thread");429return OMR_ERROR_INTERNAL;430}431432compInfo->acquireCompMonitor(crashedThread);433compInfo->getPersistentInfo()->setDisableFurtherCompilation(true);434compInfo->purgeMethodQueue(compilationFailure);435compInfo->releaseCompMonitor(crashedThread);436437recompilationThreadInfo->resumeCompilationThread();438439TR::FILE *jitdumpFile = trfopen(label, "ab", false);440if (NULL == jitdumpFile)441{442j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_NO_OPEN_READ, label);443return OMR_ERROR_INTERNAL;444}445446trfprintf(jitdumpFile,447"<?xml version=\"1.0\" standalone=\"no\"?>\n"448"<jitDump>\n"449);450451try452{453// Process user defined options first. The user can specify any method signature to be recompiled at an arbitrary454// dump event. This is typically used for debugging purposes so we process this option first if it exists.455if (NULL != agent->dumpOptions)456{457const char *indexOfDot = strchr(agent->dumpOptions, '.');458const char *indexOfParen = strchr(agent->dumpOptions, '(');459460if ((NULL != indexOfDot) && (NULL != indexOfParen))461{462TR::VMAccessCriticalSection findUserMethod(TR_J9VMBase::get(jitConfig, crashedThread));463464const char *className = agent->dumpOptions;465U_32 classNameLength = static_cast<U_32>(indexOfDot - agent->dumpOptions);466const char *methodName = indexOfDot + 1;467U_32 methodNameLength = static_cast<U_32>(indexOfParen - methodName);468const char *methodSig = indexOfParen;469U_32 methodSigLength = strlen(methodSig);470471J9MethodFromSignatureWalkState state;472J9Method *userMethod = allMethodsFromSignatureStartDo(&state, context->javaVM, 0, className, classNameLength, methodName, methodNameLength, methodSig, methodSigLength);473while (NULL != userMethod)474{475J9JITExceptionTable *metadata = jitConfig->jitGetExceptionTableFromPC(crashedThread, reinterpret_cast<UDATA>(userMethod->extra));476if (NULL != metadata)477{478auto *bodyInfo = reinterpret_cast<TR_PersistentJittedBodyInfo *>(metadata->bodyInfo);479if (NULL != bodyInfo)480{481if (NULL == threadCompInfo)482{483// We are an application thread484jitDumpRecompileWithTracing(485crashedThread,486userMethod,487compInfo,488bodyInfo->getHotness(),489bodyInfo->getIsProfilingBody(),490NULL,491bodyInfo->getIsAotedBody(),492bodyInfo->getStartPCAfterPreviousCompile(),493jitdumpFile494);495}496else497{498// We are a compilation thread499500// See comment below for the same call on why this is needed501TR::CompilationInfoPerThreadBase::UninterruptibleOperation jitDumpForCrashedCompilationThread(*threadCompInfo);502503// See comment below for the same call on why this is needed504TR::VMAccessCriticalSection requestSynchronousCompilation(TR_J9VMBase::get(jitConfig, crashedThread));505506jitDumpRecompileWithTracing(507crashedThread,508userMethod,509compInfo,510bodyInfo->getHotness(),511bodyInfo->getIsProfilingBody(),512NULL,513bodyInfo->getIsAotedBody(),514bodyInfo->getStartPCAfterPreviousCompile(),515jitdumpFile516);517}518}519}520userMethod = allMethodsFromSignatureNextDo(&state);521}522allMethodsFromSignatureEndDo(&state);523}524}525526if (NULL == threadCompInfo)527{528// We are an application thread529530if (NULL != crashedThread->gpInfo)531{532// The stack walker may not be able to walk the stack if the crash did not happen on a transition frame. In533// such cases the stack walker will resume walking the stack on the last known valid point, which will be a534// transition frame further up the stack (ex. INT -> JIT transition frame). This will result in the stack535// walker potentially skipping some JIT methods on the backtrace. This is not desirable. Chances are high536// that the crash happen because of a miscompilation in the first JIT compiled method on the stack, so it537// is imperative that we recompile the method we actually crashed in.538const char *name;539void *value;540U_32 infoType = j9sig_info(crashedThread->gpInfo, J9PORT_SIG_CONTROL, J9PORT_SIG_CONTROL_PC, &name, &value);541542if (J9PORT_SIG_VALUE_ADDRESS == infoType)543{544J9JITExceptionTable *metadata = jitConfig->jitGetExceptionTableFromPC(crashedThread, *reinterpret_cast<UDATA*>(value));545if (NULL != metadata)546{547auto *bodyInfo = reinterpret_cast<TR_PersistentJittedBodyInfo *>(metadata->bodyInfo);548if (NULL != bodyInfo)549{550jitDumpRecompileWithTracing(551crashedThread,552metadata->ramMethod,553compInfo,554bodyInfo->getHotness(),555bodyInfo->getIsProfilingBody(),556NULL,557bodyInfo->getIsAotedBody(),558bodyInfo->getStartPCAfterPreviousCompile(),559jitdumpFile560);561}562}563}564}565566J9StackWalkState walkState;567walkState.userData1 = compInfo;568walkState.userData2 = jitdumpFile;569walkState.walkThread = crashedThread;570walkState.skipCount = 0;571walkState.maxFrames = 16;572walkState.flags = (573J9_STACKWALK_VISIBLE_ONLY |574J9_STACKWALK_SKIP_INLINES |575J9_STACKWALK_COUNT_SPECIFIED |576J9_STACKWALK_ITERATE_FRAMES |577J9_STACKWALK_NO_ERROR_REPORT578);579walkState.frameWalkFunction = jitDumpStackFrameIterator;580581crashedThread->javaVM->walkStackFrames(crashedThread, &walkState);582}583else584{585// We are a compilation thread586587// Printing the crashed thread trees or any similar operation on the crashed thread may result in having to588// acquire VM access (ex. to get a class signature). Other VM events, such as VM shutdown or the GC unloading589// classes may cause compilations to be interrupted. Because the crashed thread is not a diagnostic thread,590// the call to print the crashed thread IL may get interrupted and the jitdump will be incomplete. We prevent591// this from occuring by disallowing interruptions until we are done generating the jitdump.592TR::CompilationInfoPerThreadBase::UninterruptibleOperation jitDumpForCrashedCompilationThread(*threadCompInfo);593594TR::Compilation *comp = threadCompInfo->getCompilation();595if (NULL == comp)596{597j9nls_printf(PORTLIB, J9NLS_ERROR | J9NLS_STDERR, J9NLS_DMP_ERROR_IN_DUMP_STR, "JIT", "Could not locate the compilation object");598trfclose(jitdumpFile);599return OMR_ERROR_INTERNAL;600}601602#if defined(J9VM_OPT_JITSERVER)603if (comp->isOutOfProcessCompilation())604{605// Inform the client that JitDump has started and is about to trace IL of the crashed thread606TR_MethodToBeCompiled *entry = threadCompInfo->getMethodBeingCompiled();607JITServer::ServerStream *stream = entry->_stream;608stream->write(JITServer::MessageType::jitDumpPrintIL, JITServer::Void());609stream->read<JITServer::Void>();610}611#endif612613traceILOfCrashedThread(crashedThread, comp, jitdumpFile);614615TR_MethodToBeCompiled *methodBeingCompiled = threadCompInfo->getMethodBeingCompiled();616if (NULL != methodBeingCompiled && methodBeingCompiled->getMethodDetails().isOrdinaryMethod())617{618j9nls_printf(PORTLIB, J9NLS_INFO | J9NLS_STDERR, J9NLS_DMP_JIT_ORDINARY_METHOD);619620{621// The current thread is a compilation thread which may or may not currently hold VM access. The request622// for recompilation to generate the jitdump will be performed synchronously for which the code path we623// will take will be the same as if we were an application thread. We will take the synchronous request624// path in `compileOnSeparateThread` which ends up releasing VM access prior to waiting on the diagnostic625// thread to finish the queued compile. To avoid deadlocks we must acquire VM access here.626TR::VMAccessCriticalSection requestSynchronousCompilation(TR_J9VMBase::get(jitConfig, crashedThread));627628// request the compilation629jitDumpRecompileWithTracing(630crashedThread,631(J9Method *)(comp->getCurrentMethod()->getPersistentIdentifier()),632compInfo,633(TR_Hotness)comp->getOptLevel(),634comp->isProfilingCompilation(),635comp->getOptions(),636comp->compileRelocatableCode(),637methodBeingCompiled->_oldStartPC,638jitdumpFile639);640}641}642}643}644catch (const std::exception &e)645{646const char *exceptionName;647648#if defined(J9ZOS390)649// Compiling with -Wc,lp64 results in a crash on z/OS when trying650// to call the what() virtual method of the exception.651exceptionName = "std::exception";652#else653exceptionName = e.what();654#endif655656trfprintf(jitdumpFile, "\n=== EXCEPTION THROWN (%s) ===\n", exceptionName);657}658659trfprintf(jitdumpFile, "</jitDump>\n");660trfflush(jitdumpFile);661trfclose(jitdumpFile);662663recompilationThreadInfo->suspendCompilationThread();664665compInfo->getPersistentInfo()->setDisableFurtherCompilation(false);666667return OMR_ERROR_NONE;668}669670671