Path: blob/master/runtime/codert_vm/decomp.cpp
5986 views
/*******************************************************************************1* Copyright (c) 1991, 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 <string.h>23#include "j9.h"24#include "j9protos.h"25#include "j9consts.h"26#include "j9cp.h"27#include "rommeth.h"28#include "jilconsts.h"29#include "jitprotos.h"30#include "j9protos.h"31#include "stackwalk.h"32#include "MethodMetaData.h"33#include "pcstack.h"34#include "ut_j9codertvm.h"35#include "jitregmap.h"36#include "pcstack.h"37#include "VMHelpers.hpp"38#include "OMR/Bytes.hpp"3940#if defined(OSX) && defined(AARCH64)41#include <pthread.h> // for pthread_jit_write_protect_np42#endif4344extern "C" {4546/* Generic rounding macro - result is a UDATA */47#define ROUND_TO(granularity, number) OMR::align((UDATA)(number), granularity)4849typedef struct {50J9JITExceptionTable * metaData;51J9Method * method;52UDATA * bp;53UDATA * a0;54UDATA * unwindSP;55UDATA * sp;56UDATA argCount;57J9Method * literals;58J9I2JState i2jState;59UDATA * j2iFrame;60UDATA preservedRegisterValues[J9SW_JIT_CALLEE_PRESERVED_SIZE];61UDATA previousFrameBytecodes;62UDATA notifyFramePop;63UDATA resolveFrameFlags;64} J9JITDecompileState;6566/* OSR result codes */67#define OSR_OK 068#define OSR_OUT_OF_MEMORY 16970/* Bit values for J9OSRFrame->flags */71#define J9OSRFRAME_NOTIFY_FRAME_POP 17273typedef struct {74J9VMThread *targetThread;75J9JITExceptionTable *metaData;76void *jitPC;77UDATA resolveFrameFlags;78UDATA *objectArgScanCursor;79UDATA *objectTempScanCursor;80J9JITStackAtlas *gcStackAtlas;81J9Method *method;82U_8 *liveMonitorMap;83U_16 numberOfMapBits;84void *inlineMap;85void *inlinedCallSite;86J9OSRFrame *osrFrame;87} J9OSRData;8889extern void _fsdSwitchToInterpPatchEntry(void *);90extern void _fsdRestoreToJITPatchEntry(void *);9192J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreter0);93J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreter1);94J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreterD);95J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreterF);96J9_EXTERN_BUILDER_SYMBOL(jitExitInterpreterJ);97J9_EXTERN_BUILDER_SYMBOL(jitDecompileOnReturn0);98J9_EXTERN_BUILDER_SYMBOL(jitDecompileOnReturn1);99J9_EXTERN_BUILDER_SYMBOL(jitDecompileOnReturnD);100J9_EXTERN_BUILDER_SYMBOL(jitDecompileOnReturnF);101J9_EXTERN_BUILDER_SYMBOL(jitDecompileOnReturnJ);102J9_EXTERN_BUILDER_SYMBOL(jitDecompileOnReturnL);103J9_EXTERN_BUILDER_SYMBOL(jitReportExceptionCatch);104J9_EXTERN_BUILDER_SYMBOL(jitDecompileAtExceptionCatch);105J9_EXTERN_BUILDER_SYMBOL(jitDecompileAtCurrentPC);106J9_EXTERN_BUILDER_SYMBOL(jitDecompileBeforeMethodMonitorEnter);107J9_EXTERN_BUILDER_SYMBOL(jitDecompileBeforeReportMethodEnter);108J9_EXTERN_BUILDER_SYMBOL(jitDecompileAfterAllocation);109J9_EXTERN_BUILDER_SYMBOL(jitDecompileAfterMonitorEnter);110J9_EXTERN_BUILDER_SYMBOL(executeCurrentBytecodeFromJIT);111J9_EXTERN_BUILDER_SYMBOL(enterMethodMonitorFromJIT);112J9_EXTERN_BUILDER_SYMBOL(reportMethodEnterFromJIT);113J9_EXTERN_BUILDER_SYMBOL(handlePopFramesFromJIT);114115static J9OSRFrame* findOSRFrameAtInlineDepth(J9OSRBuffer *osrBuffer, UDATA inlineDepth);116static void jitFramePopNotificationAdded(J9VMThread * currentThread, J9StackWalkState * walkState, UDATA inlineDepth);117static void decompPrintMethod(J9VMThread * currentThread, J9Method * method);118static UDATA decompileAllFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState);119static J9JITDecompilationInfo * deleteDecompilationForExistingFrame(J9VMThread * decompileThread, J9JITDecompilationInfo * info);120static J9JITDecompilationInfo * addDecompilation(J9VMThread * currentThread, J9StackWalkState * walkState, UDATA reason);121static void removeAllBreakpoints(J9VMThread * currentThread);122static void buildBytecodeFrame(J9VMThread *currentThread, J9OSRFrame *osrFrame);123static void buildInlineStackFrames(J9VMThread *currentThread, J9JITDecompileState *decompileState, J9JITDecompilationInfo *decompRecord, UDATA inlineDepth, J9OSRFrame *osrFrame);124static void performDecompile(J9VMThread * currentThread, J9JITDecompileState * decompileState, J9JITDecompilationInfo * decompRecord, J9OSRFrame *osrFrame, UDATA numberOfFrames);125static void decompileOuterFrame(J9VMThread * currentThread, J9JITDecompileState * decompileState, J9JITDecompilationInfo * decompRecord, J9OSRFrame *osrFrame);126static void markMethodBreakpointed(J9VMThread * currentThread, J9JITBreakpointedMethod * breakpointedMethod);127static UDATA codeBreakpointAddedFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState);128static void decompileAllMethodsInAllStacks(J9VMThread * currentThread, UDATA reason);129static void markMethodUnbreakpointed(J9VMThread * currentThread, J9JITBreakpointedMethod * breakpointedMethod);130static void reinstallAllBreakpoints(J9VMThread * currentThread);131static UDATA decompileMethodFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState);132static void deleteAllDecompilations(J9VMThread * currentThread, UDATA reason, J9Method * method);133static void freeDecompilationRecord(J9VMThread * decompileThread, J9JITDecompilationInfo * info, UDATA retain);134static UDATA osrAllFramesSize(J9VMThread *currentThread, J9JITExceptionTable *metaData, void *jitPC, UDATA resolveFrameFlags);135static UDATA performOSR(J9VMThread *currentThread, J9StackWalkState *walkState, J9OSRBuffer *osrBuffer, U_8 *osrScratchBuffer, UDATA scratchBufferSize, UDATA jitStackFrameSize, UDATA *mustDecompile);136static UDATA* jitLocalSlotAddress(J9VMThread * currentThread, J9StackWalkState *walkState, UDATA slot, UDATA inlineDepth);137static void jitResetAllMethods(J9VMThread *currentThread);138static void fixStackForNewDecompilation(J9VMThread * currentThread, J9StackWalkState * walkState, J9JITDecompilationInfo *info, UDATA reason, J9JITDecompilationInfo **link);139static UDATA roundedOSRScratchBufferSize(J9VMThread * currentThread, J9JITExceptionTable *metaData, void *jitPC);140static j9object_t* getObjectSlotAddress(J9OSRData *osrData, U_16 slot);141static UDATA createMonitorEnterRecords(J9VMThread *currentThread, J9OSRData *osrData);142static UDATA initializeOSRFrame(J9VMThread *currentThread, J9OSRData *osrData);143static UDATA initializeOSRBuffer(J9VMThread *currentThread, J9OSRBuffer *osrBuffer, J9OSRData *osrData);144static UDATA getPendingStackHeight(J9VMThread *currentThread, U_8 *interpreterPC, J9Method *ramMethod, UDATA resolveFrameFlags);145static J9JITDecompilationInfo* jitAddDecompilationForFramePop(J9VMThread * currentThread, J9StackWalkState * walkState);146static J9JITDecompilationInfo* fetchAndUnstackDecompilationInfo(J9VMThread *currentThread);147static void fixSavedPC(J9VMThread *currentThread, J9JITDecompilationInfo *decompRecord);148static void dumpStack(J9VMThread *currentThread, char const *msg);149static J9ROMNameAndSignature* getNASFromInvoke(U_8 *bytecodePC, J9ROMClass *romClass);150151152/**153* Get the J9ROMNameAndSignature for an invoke bytecode.154*155* @param[in] bytecodePC the PC of the invoke156* @param[in] romClass the J9ROMClass containing the invoke bytecode157*158* @return the J9ROMNameAndSignature referenced by the invoke159*/160static J9ROMNameAndSignature*161getNASFromInvoke(U_8 *bytecodePC, J9ROMClass *romClass)162{163U_16 cpIndex = *(U_16*)(bytecodePC + 1);164J9ROMNameAndSignature* nameAndSig = NULL;165U_8 bytecode = *bytecodePC;166if (JBinvokedynamic == bytecode) {167/* Convert from callSites table index to actual cpIndex by probing the168* J9ROMClass->callSiteData table. That data is layed out as:169* callSiteCount x SRP to: J9ROMNameAndSignature, callSiteCount x U16, bsmCount x J9BSMData170*/171J9SRP *callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(romClass);172nameAndSig = SRP_PTR_GET(callSiteData + cpIndex, J9ROMNameAndSignature*);173} else {174switch(bytecode) {175case JBinvokeinterface2:176cpIndex = *(U_16*)(bytecodePC + 3);177break;178case JBinvokestaticsplit:179cpIndex = *(J9ROMCLASS_STATICSPLITMETHODREFINDEXES(romClass) + cpIndex);180break;181case JBinvokespecialsplit:182cpIndex = *(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(romClass) + cpIndex);183break;184}185J9ROMMethodRef * romMethodRef = ((J9ROMMethodRef *) &(J9_ROM_CP_FROM_ROM_CLASS(romClass)[cpIndex]));186nameAndSig = J9ROMMETHODREF_NAMEANDSIGNATURE(romMethodRef);187}188return nameAndSig;189}190191192/**193* Pop the top of the decompilation stack.194*195* @param[in] currentThread the current J9VMThread196*197* @return the top element from the decompilation stack198*/199static J9JITDecompilationInfo*200fetchAndUnstackDecompilationInfo(J9VMThread *currentThread)201{202J9JITDecompilationInfo *decompRecord = currentThread->decompilationStack;203currentThread->decompilationStack = decompRecord->next;204return decompRecord;205}206207208/**209* Restore the PC from a decompilation record to its original location.210*211* @param[in] currentThread the current J9VMThread212* @param[in] decompRecord the decompilation record213*/214static void215fixSavedPC(J9VMThread *currentThread, J9JITDecompilationInfo *decompRecord)216{217*decompRecord->pcAddress = decompRecord->pc;218}219220/**221* If the verbose stack dumper is enabled, dump the stack of the current thread.222*223* @param[in] currentThread the current J9VMThread224* @param[in] msg the header message for the stack dump225*/226static void227dumpStack(J9VMThread *currentThread, char const *msg)228{229J9JavaVM *vm = currentThread->javaVM;230if (NULL != vm->verboseStackDump) {231vm->verboseStackDump(currentThread, msg);232}233}234235236static void237decompPrintMethod(J9VMThread * currentThread, J9Method * method)238{239PORT_ACCESS_FROM_VMC(currentThread);240J9UTF8 * className = J9ROMCLASS_CLASSNAME(UNTAGGED_METHOD_CP(method)->ramClass->romClass);241J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);242J9UTF8 * name = J9ROMMETHOD_NAME(romMethod);243J9UTF8 * sig = J9ROMMETHOD_SIGNATURE(romMethod);244245Trc_Decomp_printMethod(currentThread, method, J9UTF8_LENGTH(className), J9UTF8_DATA(className), J9UTF8_LENGTH(name), J9UTF8_DATA(name), J9UTF8_LENGTH(sig), J9UTF8_DATA(sig));246}247248249static void250jitResetAllMethods(J9VMThread *currentThread)251{252J9JavaVM * vm = currentThread->javaVM;253J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;254J9Class * clazz = NULL;255J9ClassWalkState state;256257/* First mark every compiled method for retranslation and invalidate the translation */258259clazz = vmFuncs->allClassesStartDo(&state, vm, NULL);260while (clazz != NULL) {261J9Method *method = clazz->ramMethods;262U_32 methodCount = clazz->romClass->romMethodCount;263264#if defined(OSX) && defined(AARCH64)265pthread_jit_write_protect_np(0);266#endif267268while (methodCount != 0) {269UDATA extra = (UDATA)method->extra;270if (0 == (extra & J9_STARTPC_NOT_TRANSLATED)) {271/* Do not reset JIT INLs (currently in FSD there are no compiled JNI natives) */272if (0 == (J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccNative)) {273J9JITExceptionTable *metaData = vm->jitConfig->jitGetExceptionTableFromPC(currentThread, extra);274if (NULL != metaData) {275/* 0xCC is the "int3" instruction on x86.276* This will cause a crash if this instruction is executed.277* On other platforms, this will have unknown behaviour (likely a crash).278*/279*(U_8*)method->extra = 0xCC;280}281vmFuncs->initializeMethodRunAddress(currentThread, method);282}283}284method += 1;285methodCount -= 1;286}287288#if defined(OSX) && defined(AARCH64)289pthread_jit_write_protect_np(1);290#endif291292clazz = vmFuncs->allClassesNextDo(&state);293}294vmFuncs->allClassesEndDo(&state);295296/* Now fix all the JIT vTables */297298clazz = vmFuncs->allClassesStartDo(&state, vm, NULL);299while (clazz != NULL) {300/* Interface classes do not have vTables, so skip them */301if (!J9ROMCLASS_IS_INTERFACE(clazz->romClass)) {302UDATA *vTableWriteCursor = JIT_VTABLE_START_ADDRESS(clazz);303304J9VTableHeader *vTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(clazz);305J9Method **vTableReadCursor = J9VTABLE_FROM_HEADER(vTableHeader);306UDATA vTableSize = vTableHeader->size;307308/* Put invalid entries in the obsolete JIT vTables and reinitialize the current ones */309if (J9_IS_CLASS_OBSOLETE(clazz)) {310while (0 != vTableSize) {311*vTableWriteCursor = (UDATA)-1;312vTableWriteCursor -= 1;313vTableSize -= 1;314}315} else {316while (0 != vTableSize) {317J9Method *method = *vTableReadCursor;318vTableReadCursor += 1;319vmFuncs->fillJITVTableSlot(currentThread, vTableWriteCursor, method);320vTableWriteCursor -= 1;321vTableSize -= 1;322}323}324}325clazz = vmFuncs->allClassesNextDo(&state);326}327vmFuncs->allClassesEndDo(&state);328}329330331332#if (defined(J9VM_INTERP_HOT_CODE_REPLACEMENT)) /* priv. proto (autogen) */333334J9JITDecompilationInfo *335jitCleanUpDecompilationStack(J9VMThread * currentThread, J9StackWalkState * walkState, UDATA dropCurrentFrame)336{337PORT_ACCESS_FROM_VMC(currentThread);338J9JITDecompilationInfo * current;339J9JITDecompilationInfo * currentFrameDecompile = NULL;340341current = currentThread->decompilationStack;342while (current != walkState->decompilationStack) {343J9JITDecompilationInfo * temp = current;344345if (!dropCurrentFrame) {346if (current->bp == walkState->bp) {347currentFrameDecompile = current;348break;349}350}351current = current->next;352freeDecompilationRecord(currentThread, temp, FALSE);353}354currentThread->decompilationStack = current;355356return currentFrameDecompile;357}358359#endif /* J9VM_INTERP_HOT_CODE_REPLACEMENT (autogen) */360361362void363jitCodeBreakpointAdded(J9VMThread * currentThread, J9Method * method)364{365PORT_ACCESS_FROM_VMC(currentThread);366J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;367J9JITBreakpointedMethod * breakpointedMethod;368J9JITBreakpointedMethod * breakpointedMethods = jitConfig->breakpointedMethods;369J9VMThread * loopThread;370371/* Called under exclusive access, so no mutex required */372373Trc_Decomp_jitCodeBreakpointAdded_Entry(currentThread, method);374decompPrintMethod(currentThread, method);375376breakpointedMethod = breakpointedMethods;377while (breakpointedMethod) {378if (breakpointedMethod->method == method) {379++(breakpointedMethod->count);380Trc_Decomp_jitCodeBreakpointAdded_incCount(currentThread, breakpointedMethod->count);381return;382}383breakpointedMethod = breakpointedMethod->link;384}385386Trc_Decomp_jitCodeBreakpointAdded_newEntry(currentThread);387388breakpointedMethod = (J9JITBreakpointedMethod *) j9mem_allocate_memory(sizeof(J9JITBreakpointedMethod), OMRMEM_CATEGORY_JIT);389if (!breakpointedMethod) {390j9tty_printf(PORTLIB, "\n*** alloc failure in jitPermanentBreakpointAdded ***\n");391Assert_Decomp_breakpointFailed();392}393394breakpointedMethod->link = breakpointedMethods;395jitConfig->breakpointedMethods = breakpointedMethod;396397breakpointedMethod->method = method;398breakpointedMethod->count = 1;399markMethodBreakpointed(currentThread, breakpointedMethod);400401Trc_Decomp_jitCodeBreakpointAdded_hasBeenTranslated(currentThread, breakpointedMethod->hasBeenTranslated);402403loopThread = currentThread;404do {405J9StackWalkState walkState;406407walkState.userData1 = method;408walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_MAINTAIN_REGISTER_MAP;409walkState.skipCount = 0;410walkState.frameWalkFunction = codeBreakpointAddedFrameIterator;411walkState.walkThread = loopThread;412currentThread->javaVM->walkStackFrames(currentThread, &walkState);413} while ((loopThread = loopThread->linkNext) != currentThread);414415Trc_Decomp_jitCodeBreakpointAdded_Exit(currentThread);416}417418419void420jitCodeBreakpointRemoved(J9VMThread * currentThread, J9Method * method)421{422PORT_ACCESS_FROM_VMC(currentThread);423J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;424J9JITBreakpointedMethod ** previous = &(jitConfig->breakpointedMethods);425J9JITBreakpointedMethod * breakpointedMethod;426427/* Called under exclusive access, so no mutex required */428429Trc_Decomp_jitCodeBreakpointRemoved_Entry(currentThread, method);430decompPrintMethod(currentThread, method);431432while ((breakpointedMethod = *previous) != NULL) {433if (breakpointedMethod->method == method) {434UDATA count;435436if ( (count = --(breakpointedMethod->count)) == 0) {437Trc_Decomp_jitCodeBreakpointAdded_fixingMethods(currentThread);438markMethodUnbreakpointed(currentThread, breakpointedMethod);439*previous = breakpointedMethod->link;440j9mem_free_memory(breakpointedMethod);441deleteAllDecompilations(currentThread, JITDECOMP_CODE_BREAKPOINT, method);442}443444Trc_Decomp_jitCodeBreakpointRemoved_decCount(currentThread, count);445446return;447}448previous = &(breakpointedMethod->link);449}450451Trc_Decomp_jitCodeBreakpointAdded_Failed(currentThread);452}453454455static UDATA456codeBreakpointAddedFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState)457{458/* Decompile JIT frames running the breakpointed method */459460if (walkState->jitInfo && (walkState->method == (J9Method *) walkState->userData1)) {461addDecompilation(currentThread, walkState, JITDECOMP_CODE_BREAKPOINT);462}463464return J9_STACKWALK_KEEP_ITERATING;465}466467468#if (defined(J9VM_INTERP_HOT_CODE_REPLACEMENT)) /* priv. proto (autogen) */469470void471jitHotswapOccurred(J9VMThread * currentThread)472{473/* We have exclusive */474475Trc_Decomp_jitHotswapOccurred_Entry(currentThread);476477/* Remove all breakpoints before resetting the methods */478479removeAllBreakpoints(currentThread);480481/* Find every method which has been translated and mark it for retranslation */482483jitResetAllMethods(currentThread);484485/* Reinstall the breakpoints */486487reinstallAllBreakpoints(currentThread);488489/* Mark every JIT method in every stack for decompilation */490491decompileAllMethodsInAllStacks(currentThread, JITDECOMP_HOTSWAP);492493Trc_Decomp_jitHotswapOccurred_Exit(currentThread);494}495496#endif /* J9VM_INTERP_HOT_CODE_REPLACEMENT (autogen) */497498499void500jitDecompileMethod(J9VMThread * currentThread, J9JITDecompilationInfo * decompRecord)501{502J9JITDecompileState decompileState;503J9StackWalkState walkState;504J9OSRBuffer *osrBuffer = &decompRecord->osrBuffer;505UDATA numberOfFrames = osrBuffer->numberOfFrames;506J9OSRFrame *osrFrame = (J9OSRFrame*)(osrBuffer + 1);507508/* Collect the required information from the stack - top visible frame is the decompile frame */509walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_MAINTAIN_REGISTER_MAP | J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_SAVE_STACKED_REGISTERS;510walkState.skipCount = 0;511walkState.frameWalkFunction = decompileMethodFrameIterator;512walkState.walkThread = currentThread;513walkState.userData1 = &decompileState;514walkState.userData2 = NULL;515currentThread->javaVM->walkStackFrames(currentThread, &walkState);516517performDecompile(currentThread, &decompileState, decompRecord, osrFrame, numberOfFrames);518519freeDecompilationRecord(currentThread, decompRecord, TRUE);520}521522/**523* Find the pending stack height for a frame.524*525* @param[in] *currentThread current thread526* @param[in] *interpreterP the bytecoded PC527* @param[in] *method the J9Method528* @param[in] resolveFrameFlags the flags of the preceding resolve frame, or 0 if not preceded by a resolve frame529*530* @return the pending stack height531*/532533static UDATA534getPendingStackHeight(J9VMThread *currentThread, U_8 *interpreterPC, J9Method *ramMethod, UDATA resolveFrameFlags)535{536UDATA pendingStackHeight = 0;537538/* If the JIT frame has not been built, the pending stack height is 0. If we're at an exception catch,539* the height is 0 because the decompile return point will push the pending exception.540*/541UDATA resolveFrameType = resolveFrameFlags & J9_STACK_FLAGS_JIT_FRAME_SUB_TYPE_MASK;542switch(resolveFrameType) {543case J9_STACK_FLAGS_JIT_STACK_OVERFLOW_RESOLVE_FRAME:544case J9_STACK_FLAGS_JIT_EXCEPTION_CATCH_RESOLVE:545break;546default:547J9ROMClass *romClass = J9_CLASS_FROM_METHOD(ramMethod)->romClass;548J9ROMMethod * originalROMMethod = getOriginalROMMethod(ramMethod);549UDATA offsetPC = interpreterPC - J9_BYTECODE_START_FROM_RAM_METHOD(ramMethod);550J9JavaVM *vm = currentThread->javaVM;551J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;552J9PortLibrary *portLibrary = vm->portLibrary;553U_8 bytecode = *interpreterPC;554/* Use the stack mapper to determine the pending stack height */555pendingStackHeight = (UDATA)vmFuncs->j9stackmap_StackBitsForPC(portLibrary, offsetPC, romClass, originalROMMethod, NULL, 0, NULL, NULL, NULL);556/* All invokes consider their arguments not to be pending - remove the arguments from the pending stack */557switch(bytecode) {558case JBinvokevirtual:559case JBinvokespecial:560case JBinvokespecialsplit:561case JBinvokeinterface:562case JBinvokeinterface2:563case JBinvokehandle:564case JBinvokehandlegeneric:565/* Remove implicit receiver from pending stack */566pendingStackHeight -= 1;567/* Intentional fall-through */568case JBinvokedynamic:569case JBinvokestatic:570case JBinvokestaticsplit:571/* Remove arguments from pending stack */572pendingStackHeight -= getSendSlotsFromSignature(J9UTF8_DATA(J9ROMNAMEANDSIGNATURE_SIGNATURE(getNASFromInvoke(interpreterPC, romClass))));573break;574}575/* Reduce the pending stack height for the resolve special cases */576switch (resolveFrameType) {577case J9_STACK_FLAGS_JIT_MONITOR_ENTER_RESOLVE:578/* Decompile after monitorenter completes. Remove the object from the pending stack. */579pendingStackHeight -= 1;580break;581case J9_STACK_FLAGS_JIT_ALLOCATION_RESOLVE:582/* Decompile after allocation completes. The JIT has not mapped the bytecode parameters in the pending stack */583switch (bytecode) {584case JBanewarray:585case JBnewarray: /* 1 slot (size) stacked */586pendingStackHeight -= 1;587break;588case JBmultianewarray: /* Dimensions stacked (number of dimensions is 3 bytes from the multianewarray) */589pendingStackHeight -= interpreterPC[3];590break;591case JBwithfield:592/* it will always be two slots since we only ever need to allocate qtype */593pendingStackHeight -= 2;594break;595case JBgetfield:596pendingStackHeight -= 1;597break;598default: /* JBnew/JBaconst_init - no stacked parameters*/599break;600}601}602}603Assert_CodertVM_true((IDATA)pendingStackHeight >= 0);604Trc_Decomp_decompileMethodFrameIterator_pendingCount(currentThread, pendingStackHeight);605return pendingStackHeight;606}607608609static UDATA610decompileMethodFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState)611{612J9JITDecompileState * decompileState = (J9JITDecompileState *) walkState->userData1;613614Trc_Decomp_decompileMethodFrameIterator_Entry(currentThread);615616/* If the decompile frame has already been passed, record the final information and stop walking */617618if (walkState->userData2) {619if (walkState->jitInfo) {620UDATA * valueCursor = decompileState->preservedRegisterValues;621UDATA ** mapCursor = (UDATA **) &(walkState->registerEAs);622UDATA i;623624decompileState->previousFrameBytecodes = FALSE;625626for (i = 0; i < J9SW_JIT_CALLEE_PRESERVED_SIZE; ++i) {627UDATA regNumber = jitCalleeSavedRegisterList[i];628629*(valueCursor++) = *(mapCursor[regNumber]);630}631632Trc_Decomp_decompileMethodFrameIterator_previousIsJIT(currentThread);633634} else {635Trc_Decomp_decompileMethodFrameIterator_previousIsBC(currentThread);636decompileState->previousFrameBytecodes = TRUE;637}638return J9_STACKWALK_STOP_ITERATING;639} else {640/* Current frame is the decompile frame - collect the preliminary info */641J9JITExceptionTable *metaData = walkState->jitInfo;642J9Method *method = walkState->method;643644decompileState->metaData = metaData;645decompileState->method = method;646decompileState->sp = walkState->sp;647decompileState->argCount = walkState->outgoingArgCount;648Trc_Decomp_decompileMethodFrameIterator_outgoingArgCount(currentThread, decompileState->argCount);649decompileState->bp = walkState->bp;650decompileState->a0 = walkState->arg0EA;651decompileState->literals = method;652decompileState->unwindSP = walkState->unwindSP;653decompileState->j2iFrame = walkState->j2iFrame;654memcpy(&(decompileState->i2jState), walkState->i2jState, sizeof(J9I2JState));655decompileState->resolveFrameFlags = walkState->resolveFrameFlags;656657/* Walk the next frame regardless of its visibility */658659walkState->userData2 = (void *) 1;660walkState->flags &= ~J9_STACKWALK_VISIBLE_ONLY;661}662663Trc_Decomp_decompileMethodFrameIterator_Exit(currentThread);664665return J9_STACKWALK_KEEP_ITERATING;666}667668669/**670* Push a bytecode frame based on an OSR frame. Assumes that a bytecode frame671* (either pure or J2I) is already on the top of stack.672*673* @param[in] *currentThread current thread674* @param[in] *osrFrame the OSR frame from which to copy the information675*/676static void677buildBytecodeFrame(J9VMThread *currentThread, J9OSRFrame *osrFrame)678{679J9Method *method = osrFrame->method;680U_8 *bytecodePC = osrFrame->bytecodePCOffset + J9_BYTECODE_START_FROM_RAM_METHOD(method);681UDATA numberOfLocals = osrFrame->numberOfLocals;682UDATA maxStack = osrFrame->maxStack;683UDATA pendingStackHeight = osrFrame->pendingStackHeight;684UDATA *locals = ((UDATA*)(osrFrame + 1)) + maxStack;685UDATA *pending = locals - pendingStackHeight;686UDATA *sp = currentThread->sp;687UDATA *a0 = currentThread->arg0EA;688U_8 *pc = currentThread->pc;689J9Method *literals = currentThread->literals;690UDATA *newA0 = sp - 1;691J9SFStackFrame *stackFrame = NULL;692693/* Push the locals */694sp -= numberOfLocals;695memcpy(sp, locals, numberOfLocals * sizeof(UDATA));696697/* Push the stack frame */698stackFrame = (J9SFStackFrame*)sp - 1;699stackFrame->savedPC = pc;700stackFrame->savedCP = literals;701stackFrame->savedA0 = a0;702703/* Push the pendings */704sp = (UDATA*)stackFrame - pendingStackHeight;705memcpy(sp, pending, pendingStackHeight * sizeof(UDATA));706707/* Update the root values in the J9VMThread */708currentThread->arg0EA = newA0;709currentThread->pc = bytecodePC;710currentThread->literals = method;711currentThread->sp = sp;712}713714715/**716* Recursive helper for decompiling inlined frames.717*718* @param[in] *currentThread current thread719* @param[in] *decompileState the decompilation state copied from the stack walk720* @param[in] *decompRecord the decompilation record721* @param[in] inlineDepth the depth of inlining, 0 for the outer frame722* @param[in] *osrFrame the OSR frame from which to copy the information723*/724static void725buildInlineStackFrames(J9VMThread *currentThread, J9JITDecompileState *decompileState, J9JITDecompilationInfo *decompRecord, UDATA inlineDepth, J9OSRFrame *osrFrame)726{727J9JavaVM *vm = currentThread->javaVM;728J9MonitorEnterRecord *firstEnterRecord = osrFrame->monitorEnterRecords;729J9Method *method = osrFrame->method;730if (0 == inlineDepth) {731decompileOuterFrame(currentThread, decompileState, decompRecord, osrFrame);732} else {733J9OSRFrame *nextOSRFrame = (J9OSRFrame*)((U_8*)osrFrame + osrFrameSize(method));734buildInlineStackFrames(currentThread, decompileState, decompRecord, inlineDepth - 1, nextOSRFrame);735buildBytecodeFrame(currentThread, osrFrame);736}737/* Fix all of the monitor enter records for this frame to point to the new arg0EA.738* Filter out the record for the syncObject in synchronized methods. Only one such739* record will ever be detected in any frame. Link the remaining records into the list.740*/741if (NULL != firstEnterRecord) {742J9MonitorEnterRecord listHead;743J9MonitorEnterRecord *lastEnterRecord = &listHead;744J9MonitorEnterRecord *enterRecord = firstEnterRecord;745UDATA *arg0EA = currentThread->arg0EA;746j9object_t syncObject = NULL;747if (J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccSynchronized) {748syncObject = *(j9object_t*)(arg0EA - osrFrame->numberOfLocals + 1);749}750listHead.next = firstEnterRecord;751do {752J9MonitorEnterRecord *nextRecord = enterRecord->next;753if (enterRecord->object == syncObject) {754syncObject = NULL; /* Make sure syncObject isn't matched more than once */755lastEnterRecord->next = nextRecord;756pool_removeElement(currentThread->monitorEnterRecordPool, enterRecord);757} else {758enterRecord->arg0EA = CONVERT_TO_RELATIVE_STACK_OFFSET(currentThread, arg0EA);759lastEnterRecord = enterRecord;760}761enterRecord = nextRecord;762} while (NULL != enterRecord);763lastEnterRecord->next = currentThread->monitorEnterRecords;764currentThread->monitorEnterRecords = listHead.next;765}766767/* If this frame has a notify frame pop pending, set the bit */768769if (osrFrame->flags & J9OSRFRAME_NOTIFY_FRAME_POP) {770UDATA *bp = currentThread->arg0EA - osrFrame->numberOfLocals;771Trc_Decomp_performDecompile_addedPopNotification(currentThread, bp);772*bp |= J9SF_A0_REPORT_FRAME_POP_TAG;773}774}775776777/**778* Perform decompilation after gather information from the stack walk.779*780* @param[in] *currentThread current thread781* @param[in] *decompileState the decompilation state copied from the stack walk782* @param[in] *decompRecord the decompilation record783* @param[in] *osrFrame the first OSR frame to rebuild784* @param[in] numberOfFrames the total number of frames to rebuild785*/786static void787performDecompile(J9VMThread *currentThread, J9JITDecompileState *decompileState, J9JITDecompilationInfo *decompRecord, J9OSRFrame *osrFrame, UDATA numberOfFrames)788{789J9JavaVM *vm = currentThread->javaVM;790UDATA outgoingArgs[255];791UDATA outgoingArgCount = decompileState->argCount;792UDATA inlineDepth = numberOfFrames - 1;793794Trc_Decomp_performDecompile_Entry(currentThread);795796dumpStack(currentThread, "before decompilation");797798if (FALSE == decompRecord->usesOSR) {799/* Not compiled with OSR - copy stack slots from JIT frame into OSR frame */800UDATA *jitTempBase = ((UDATA *) (((U_8 *) decompileState->bp) + ((J9JITStackAtlas *) decompileState->metaData->gcStackAtlas)->localBaseOffset)) + decompileState->metaData->tempOffset;801UDATA *osrTempBase = ((UDATA*)(osrFrame + 1)) + osrFrame->maxStack;802J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(osrFrame->method);803UDATA argCount = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod);804UDATA tempCount = osrFrame->numberOfLocals - argCount;805UDATA pendingStackHeight = osrFrame->pendingStackHeight;806807/* Decompiling without OSR means old-style single-frame FSD */808Assert_CodertVM_true(vm->jitConfig->fsdEnabled);809Assert_CodertVM_true(1 == numberOfFrames);810811/* The pending slots immediately precede the temps in both the OSR frame and the JIT frame, so copy them all at once */812memcpy(osrTempBase - pendingStackHeight, jitTempBase - pendingStackHeight, (tempCount + pendingStackHeight) * sizeof(UDATA));813}814815/* Temporarily copy the outgoing arguments to the C stack */816memcpy(outgoingArgs, decompileState->sp, outgoingArgCount * sizeof(UDATA));817818/* Rebuild the interpreter stack frames */819buildInlineStackFrames(currentThread, decompileState, decompRecord, inlineDepth, osrFrame);820821/* Push the outgoing arguments onto the java stack */822currentThread->sp -= outgoingArgCount;823memcpy(currentThread->sp, outgoingArgs, outgoingArgCount * sizeof(UDATA));824825Trc_Decomp_performDecompile_Exit(currentThread, currentThread->sp, currentThread->literals, currentThread->pc);826}827828829/**830* Decompile the outer (and possibly only) frame.831*832* @param[in] *currentThread current thread833* @param[in] *decompileState the decompilation state copied from the stack walk834* @param[in] *decompRecord the decompilation record835* @param[in] *osrFrame the OSR frame from which to copy the information836*/837static void838decompileOuterFrame(J9VMThread * currentThread, J9JITDecompileState * decompileState, J9JITDecompilationInfo * decompRecord, J9OSRFrame *osrFrame)839{840UDATA * newTempBase;841UDATA * oldTempBase;842UDATA * newPendingBase;843UDATA * oldPendingBase;844UDATA * stackFrame;845UDATA * newSP;846J9Method *method = osrFrame->method;847J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);848UDATA argCount = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod);849UDATA numberOfLocals = osrFrame->numberOfLocals;850UDATA tempCount = numberOfLocals - argCount;851U_8 ** jitReturnPCAddress = (U_8 **) &(((J9JITFrame *) (decompileState->bp))->returnPC);852U_8 * jitReturnPC = *jitReturnPCAddress;853UDATA * currentJ2iFrame = decompileState->j2iFrame;854UDATA pendingStackHeight = osrFrame->pendingStackHeight;855856oldTempBase = ((UDATA*)(osrFrame + 1)) + osrFrame->maxStack;857858/* Determine the shape of the new stack frame */859860newTempBase = decompileState->a0 - numberOfLocals + 1;861if (decompileState->previousFrameBytecodes) {862/* Use the I2J returnSP in this case in order to account for the possible 8-alignment of the I2J args */863UDATA * correctTempBase = UNTAG2(decompileState->i2jState.returnSP, UDATA *) - numberOfLocals;864865/* If the args were moved for alignment, copy them back to their original position */866if (newTempBase != correctTempBase) {867UDATA * newA0 = correctTempBase + numberOfLocals - 1;868memmove(correctTempBase + tempCount, newTempBase + tempCount, argCount * sizeof(UDATA));869newTempBase = correctTempBase;870decompileState->a0 = newA0;871}872stackFrame = (UDATA *) (((U_8 *) newTempBase) - sizeof(J9SFStackFrame));873} else {874stackFrame = (UDATA *) (((U_8 *) newTempBase) - sizeof(J9SFJ2IFrame));875}876newPendingBase = stackFrame - pendingStackHeight;877oldPendingBase = oldTempBase - pendingStackHeight;878newSP = newPendingBase;879880/* If the JIT stack frame has not been constructed, don't attempt to read from it */881882UDATA resolveFrameType = decompileState->resolveFrameFlags & J9_STACK_FLAGS_JIT_FRAME_SUB_TYPE_MASK;883if (J9_STACK_FLAGS_JIT_STACK_OVERFLOW_RESOLVE_FRAME == resolveFrameType) {884Trc_Decomp_performDecompile_monitorNotEntered(currentThread);885886/* Temps have not been pushed yet - zero them and set up the sync object (if any) */887888memset(newTempBase, 0, tempCount * sizeof(UDATA));889if (romMethod->modifiers & J9AccSynchronized) {890if (romMethod->modifiers & J9AccStatic) {891newTempBase[0] = (UDATA)J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD(method));892} else {893newTempBase[0] = *(decompileState->a0);894}895} else if (J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod)) {896newTempBase[0] = *(decompileState->a0);897}898} else {899/* Copy the temps to their new location */900901memcpy(newTempBase, oldTempBase, tempCount * sizeof(UDATA));902}903904/* Copy pending pushes */905906memcpy(newPendingBase, oldPendingBase, pendingStackHeight * sizeof(UDATA));907908/* Create the stack frame, either a pure bytecode frame or a J2I frame, depending on the previous frame. */909910if (decompileState->previousFrameBytecodes) {911J9SFStackFrame * bytecodeFrame = (J9SFStackFrame *) stackFrame;912913Trc_Decomp_performDecompile_buildingBCFrame(currentThread, stackFrame);914915bytecodeFrame->savedPC = decompileState->i2jState.pc;916bytecodeFrame->savedCP = decompileState->i2jState.literals;917bytecodeFrame->savedA0 = decompileState->i2jState.a0;918} else {919J9SFJ2IFrame * j2iFrame = (J9SFJ2IFrame *) stackFrame;920char * returnChar;921J9JITDecompilationInfo * info;922923Trc_Decomp_performDecompile_buildingJ2IFrame(currentThread, stackFrame);924925memcpy(&(j2iFrame->i2jState), &(decompileState->i2jState), sizeof(J9I2JState));926memcpy(&(j2iFrame->J9SW_LOWEST_MEMORY_PRESERVED_REGISTER), decompileState->preservedRegisterValues, J9SW_JIT_CALLEE_PRESERVED_SIZE * sizeof(UDATA));927j2iFrame->specialFrameFlags = J9_STACK_FLAGS_JIT_CALL_IN_FRAME | J9_STACK_FLAGS_JIT_CALL_IN_TYPE_J2_I;928j2iFrame->returnAddress = jitReturnPC;929j2iFrame->previousJ2iFrame = currentJ2iFrame;930currentJ2iFrame = (UDATA *) &(j2iFrame->taggedReturnSP);931932returnChar = (char *) J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(romMethod));933while (*returnChar++ != ')') ;934switch(*returnChar) {935case 'V':936j2iFrame->exitPoint = J9_BUILDER_SYMBOL(jitExitInterpreter0);937break;938case 'D':939j2iFrame->exitPoint = J9_BUILDER_SYMBOL(jitExitInterpreterD);940break;941case 'F':942j2iFrame->exitPoint = J9_BUILDER_SYMBOL(jitExitInterpreterF);943break;944case 'J':945#ifdef J9VM_ENV_DATA64946case '[':947case 'L':948#endif949j2iFrame->exitPoint = J9_BUILDER_SYMBOL(jitExitInterpreterJ);950break;951default:952j2iFrame->exitPoint = J9_BUILDER_SYMBOL(jitExitInterpreter1);953break;954}955956#ifdef J9SW_NEEDS_JIT_2_INTERP_CALLEE_ARG_POP957j2iFrame->taggedReturnSP = (UDATA *) (((U_8 *) (((UDATA *) (j2iFrame + 1)) + argCount + tempCount)));958#else959j2iFrame->taggedReturnSP = (UDATA *) (((U_8 *) (((UDATA *) (j2iFrame + 1)) + tempCount)));960#endif961962/* If the next thing on the decompilation stack used to point to the return address save slot in the decompiled JIT frame, point it to the slot in the J2I frame. */963964if ((info = currentThread->decompilationStack) != NULL) {965if (info->pcAddress == jitReturnPCAddress) {966Trc_Decomp_performDecompile_fixingDecompStack(currentThread, info, info->pcAddress, &(j2iFrame->returnAddress), info->pc);967info->pcAddress = &(j2iFrame->returnAddress);968}969}970971}972973/* Fill in vmThread values for bytecode execution */974975currentThread->pc = osrFrame->bytecodePCOffset + J9_BYTECODE_START_FROM_RAM_METHOD(osrFrame->method);976currentThread->literals = decompileState->literals;977currentThread->arg0EA = decompileState->a0;978currentThread->sp = newSP;979currentThread->j2iFrame = currentJ2iFrame;980981/* If the outer framed failed a method monitor enter, hide the interpreted version to prevent exception throw982* from exiting the monitor that was never entered.983*/984if (J9_STACK_FLAGS_JIT_FAILED_METHOD_MONITOR_ENTER_RESOLVE == resolveFrameType) {985newTempBase[-1] |= J9SF_A0_INVISIBLE_TAG;986}987}988989990/**991* Fix the java stack to account for a newly-added decompilation. This involves modifying992* the return address in the stack which would be used to return to the frame for which the993* decompilation was added.994*995* @param[in] *currentThread current thread996* @param[in] *walkState stack walk state (already at the OSR point)997* @param[in] *info the new decompilation record998* @param[in] reason the reason for the decompilation999* @param[in] **link pointer to the next pointer of the previous decompilation record1000* (this may be the root of the decompilation stack)1001*/1002static void1003fixStackForNewDecompilation(J9VMThread * currentThread, J9StackWalkState * walkState, J9JITDecompilationInfo *info, UDATA reason, J9JITDecompilationInfo **link)1004{1005J9JavaVM* vm = currentThread->javaVM;1006U_8 ** pcStoreAddress = walkState->pcAddress;10071008/* Fill in the decompilation record and link it into the stack */10091010info->pcAddress = walkState->pcAddress;1011info->bp = walkState->bp;1012info->method = walkState->method;1013info->reason = reason;1014info->pc = walkState->pc;1015info->next = *link;1016*link = info;10171018/* Slam the return address to point to the appropriate decompile */10191020if (0 != walkState->resolveFrameFlags) {1021UDATA resolveFrameType = walkState->resolveFrameFlags & J9_STACK_FLAGS_JIT_FRAME_SUB_TYPE_MASK;1022switch(resolveFrameType) {1023case J9_STACK_FLAGS_JIT_STACK_OVERFLOW_RESOLVE_FRAME:1024if (J9_ARE_ANY_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method)->modifiers, J9AccSynchronized)) {1025Trc_Decomp_addDecompilation_beforeSyncMonitorEnter(currentThread);1026*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileBeforeMethodMonitorEnter);1027break;1028}1029/* Intentional fall-through */1030case J9_STACK_FLAGS_JIT_METHOD_MONITOR_ENTER_RESOLVE:1031Trc_Decomp_addDecompilation_beforeReportMethodEnter(currentThread);1032*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileBeforeReportMethodEnter);1033break;1034case J9_STACK_FLAGS_JIT_MONITOR_ENTER_RESOLVE:1035Trc_Decomp_addDecompilation_atMonitorEnter(currentThread);1036*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileAfterMonitorEnter);1037break;1038case J9_STACK_FLAGS_JIT_ALLOCATION_RESOLVE:1039Trc_Decomp_addDecompilation_atAllocate(currentThread);1040*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileAfterAllocation);1041break;1042case J9_STACK_FLAGS_JIT_EXCEPTION_CATCH_RESOLVE:1043/* Decompile during jitReportExceptionCatch */1044Trc_Decomp_addDecompilation_atExceptionCatch(currentThread);1045*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileAtExceptionCatch);1046break;1047default:1048Trc_Decomp_addDecompilation_atCurrentPC(currentThread);1049*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileAtCurrentPC);1050break;1051}1052} else {1053J9UTF8 * sig, *name;1054char * returnChar;1055J9OSRBuffer *osrBuffer = &info->osrBuffer;1056J9OSRFrame *osrFrame = (J9OSRFrame*)(osrBuffer + 1);1057U_8 * bytecodePC = osrFrame->bytecodePCOffset + J9_BYTECODE_START_FROM_RAM_METHOD(osrFrame->method);10581059Trc_Decomp_addDecompilation_atInvoke(currentThread);10601061/* PC points at an invoke - fetch the name and signature it references */1062J9ROMNameAndSignature *nameAndSig = getNASFromInvoke(bytecodePC, J9_CLASS_FROM_METHOD(osrFrame->method)->romClass);1063sig = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSig);1064name = J9ROMNAMEANDSIGNATURE_NAME(nameAndSig);1065Trc_Decomp_addDecompilation_explainInvoke(currentThread, J9UTF8_LENGTH(name), J9UTF8_DATA(name), J9UTF8_LENGTH(sig), J9UTF8_DATA(sig));10661067returnChar = (char *) J9UTF8_DATA(sig);1068while (*returnChar++ != ')') ;1069switch(*returnChar) {1070case 'V':1071*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileOnReturn0);1072break;1073case 'D':1074*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileOnReturnD);1075break;1076case 'F':1077*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileOnReturnF);1078break;1079case 'J':1080*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileOnReturnJ);1081break;1082#ifdef J9VM_ENV_DATA641083case '[':1084case 'L':1085*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileOnReturnL);1086break;1087#endif1088default:1089*pcStoreAddress = (U_8 *) J9_BUILDER_SYMBOL(jitDecompileOnReturn1);1090break;1091}1092}10931094/* Enable stack dump after linking the decompilation into the stack if -verbose:stackwalk=0 is specified */1095dumpStack(walkState->walkThread, "after fixStackForNewDecompilation");1096}109710981099static J9JITDecompilationInfo *1100addDecompilation(J9VMThread * currentThread, J9StackWalkState * walkState, UDATA reason)1101{1102PORT_ACCESS_FROM_VMC(currentThread);1103J9JavaVM* vm = currentThread->javaVM;1104J9VMThread * decompileThread = walkState->walkThread;1105J9JITDecompilationInfo * info;1106J9JITDecompilationInfo ** previous;1107J9JITDecompilationInfo * current;1108J9JITExceptionTable *metaData = walkState->jitInfo;1109UDATA allocSize = sizeof(J9JITDecompilationInfo);1110UDATA osrFrame = FALSE;1111J9OSRData osrData;11121113Trc_Decomp_addDecompilation_Entry(currentThread, walkState->method);1114decompPrintMethod(currentThread, walkState->method);1115Trc_Decomp_addDecompilation_walkStateInfo(currentThread, walkState->bp, walkState->arg0EA, walkState->constantPool, walkState->pc);1116Trc_Decomp_addDecompilation_reason(currentThread, reason,1117(reason & JITDECOMP_CODE_BREAKPOINT) ? " CODE_BREAKPOINT" : "",1118(reason & JITDECOMP_DATA_BREAKPOINT) ? " DATA_BREAKPOINT" : "",1119(reason & JITDECOMP_HOTSWAP) ? " HOTSWAP" : "",1120(reason & JITDECOMP_POP_FRAMES) ? " POP_FRAMES" : "",1121(reason & JITDECOMP_SINGLE_STEP) ? " SINGLE_STEP" : "",1122(reason & JITDECOMP_STACK_LOCALS_MODIFIED) ? " STACK_LOCALS_MODIFIED" : "",1123(reason & JITDECOMP_FRAME_POP_NOTIFICATION) ? " FRAME_POP_NOTIFICATION" : "");11241125/* addDecompilation must be called only when the walkState represents a compiled frame */1126Assert_CodertVM_true(NULL != metaData);11271128/* The decompilation is ordered by frame, with lesser frame values appearing at the beginning */11291130previous = &(decompileThread->decompilationStack);1131while ((current = *previous) != NULL) {1132/* If a decompilation for this frame already exists, tag it with the new reason and return */11331134if (current->bp == walkState->bp) {1135Trc_Decomp_addDecompilation_existingRecord(currentThread, current);1136current->reason |= reason;1137return current;1138}1139if (current->bp > walkState->bp) break;1140previous = &(current->next);1141}11421143/* OSR is not appropriate for frames whose stack frame has not been created */1144UDATA resolveFrameFlags = walkState->resolveFrameFlags;1145UDATA resolveFrameType = resolveFrameFlags & J9_STACK_FLAGS_JIT_FRAME_SUB_TYPE_MASK;1146if (J9_STACK_FLAGS_JIT_STACK_OVERFLOW_RESOLVE_FRAME != resolveFrameType) {1147if (usesOSR(currentThread, metaData)) {1148Trc_Decomp_addDecompilation_osrFrame(currentThread);1149osrFrame = TRUE;1150}1151}11521153/* Allocate and zero the decompilation record, taking the OSR buffer into account */1154allocSize += osrAllFramesSize(currentThread, metaData, walkState->pc, resolveFrameFlags);1155info = (J9JITDecompilationInfo *) j9mem_allocate_memory(allocSize, OMRMEM_CATEGORY_JIT);1156if (!info) {1157Trc_Decomp_addDecompilation_allocFailed(currentThread);1158return NULL;1159}1160memset(info, 0, allocSize);1161Trc_Decomp_addDecompilation_allocRecord(currentThread, info);1162info->usesOSR = osrFrame;11631164/* Fill in the interpreter values in the OSR buffer */1165osrData.targetThread = walkState->walkThread;1166osrData.metaData = metaData;1167osrData.jitPC = walkState->pc;1168osrData.resolveFrameFlags = walkState->resolveFrameFlags;1169osrData.objectArgScanCursor = getObjectArgScanCursor(walkState);1170osrData.objectTempScanCursor = getObjectTempScanCursor(walkState);1171if (OSR_OK != initializeOSRBuffer(currentThread, &info->osrBuffer, &osrData)) {1172Trc_Decomp_addDecompilation_allocFailed(currentThread);1173j9mem_free_memory(info);1174return NULL;1175}11761177if (osrFrame) {1178UDATA scratchBufferSize = roundedOSRScratchBufferSize(currentThread, metaData, walkState->pc);1179UDATA jitStackFrameSize = (UDATA)(walkState->arg0EA + 1) - (UDATA)walkState->unwindSP;1180void *osrScratchBuffer = j9mem_allocate_memory(scratchBufferSize + jitStackFrameSize, OMRMEM_CATEGORY_JIT);1181UDATA mustDecompile = FALSE;1182UDATA osrResultCode = OSR_OK;11831184/* TODO: use global buffer here? */1185if (NULL == osrScratchBuffer) {1186Trc_Decomp_addDecompilation_allocFailed(currentThread);1187j9mem_free_memory(info);1188return NULL;1189}11901191osrResultCode = performOSR(currentThread, walkState, &info->osrBuffer, (U_8*)osrScratchBuffer, scratchBufferSize, jitStackFrameSize, &mustDecompile);1192if (OSR_OK != osrResultCode) {1193Trc_Decomp_addDecompilation_osrFailed(currentThread);1194j9mem_free_memory(osrScratchBuffer);1195j9mem_free_memory(info);1196return NULL;1197}1198if (mustDecompile) {1199Trc_Decomp_addDecompilation_osrMustDecompile(currentThread);1200reason |= JITDECOMP_ON_STACK_REPLACEMENT;1201}1202j9mem_free_memory(osrScratchBuffer);1203}12041205/* Add the decompilation to the stack */1206fixStackForNewDecompilation(currentThread, walkState, info, reason, previous);12071208Trc_Decomp_addDecompilation_Exit(currentThread, info);12091210return info;1211}12121213void1214c_jitDecompileAtExceptionCatch(J9VMThread * currentThread)1215{1216/* Fetch the exception from the JIT */1217j9object_t exception = (j9object_t)currentThread->jitException;1218/* Fetch and unstack the decompilation information for this frame */1219J9JITDecompilationInfo *decompRecord = fetchAndUnstackDecompilationInfo(currentThread);1220U_8 *jitPC = decompRecord->pc;12211222Trc_Decomp_DecompileAtExceptionCatch_Entry(currentThread, jitPC, exception);12231224/* Simulate a call to a resolve helper to make the stack walkable */1225buildBranchJITResolveFrame(currentThread, jitPC, J9_STACK_FLAGS_JIT_EXCEPTION_CATCH_RESOLVE);12261227J9JavaVM *vm = currentThread->javaVM;1228J9JITDecompileState decompileState;1229J9StackWalkState walkState;1230J9OSRBuffer *osrBuffer = &decompRecord->osrBuffer;1231UDATA numberOfFrames = osrBuffer->numberOfFrames;1232J9OSRFrame *osrFrame = (J9OSRFrame*)(osrBuffer + 1);1233J9JITExceptionTable *metaData = NULL;12341235/* Collect the required information from the stack - top visible frame is the decompile frame */1236walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_MAINTAIN_REGISTER_MAP | J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_SAVE_STACKED_REGISTERS;1237walkState.skipCount = 0;1238walkState.frameWalkFunction = decompileMethodFrameIterator;1239walkState.walkThread = currentThread;1240walkState.userData1 = &decompileState;1241walkState.userData2 = NULL;1242vm->walkStackFrames(currentThread, &walkState);1243metaData = decompileState.metaData;12441245/* Determine in which inlined frame the exception is being caught */1246UDATA newNumberOfFrames = 1;1247void *stackMap = NULL;1248void *inlineMap = NULL;1249void *inlinedCallSite = NULL;1250/* Note we need to add 1 to the JIT PC here in order to get the correct map at the exception handler1251* because jitGetMapsFromPC is expecting a return address, so it subtracts 1. The value stored in the1252* decomp record is the start address of the compiled exception handler.1253*/1254jitGetMapsFromPC(currentThread, vm, metaData, (UDATA)jitPC + 1, &stackMap, &inlineMap);1255Assert_CodertVM_false(NULL == inlineMap);1256if (NULL != getJitInlinedCallInfo(metaData)) {1257inlinedCallSite = getFirstInlinedCallSite(metaData, inlineMap);1258if (inlinedCallSite != NULL) {1259newNumberOfFrames = getJitInlineDepthFromCallSite(metaData, inlinedCallSite) + 1;1260}1261}1262Assert_CodertVM_true(numberOfFrames >= newNumberOfFrames);1263J9Pool *monitorEnterRecordPool = currentThread->monitorEnterRecordPool;1264while (numberOfFrames != newNumberOfFrames) {1265/* Discard the monitor records for the popped frames */1266J9MonitorEnterRecord *enterRecord = osrFrame->monitorEnterRecords;1267while (NULL != enterRecord) {1268J9MonitorEnterRecord *recordToFree = enterRecord;1269enterRecord = enterRecord->next;1270pool_removeElement(monitorEnterRecordPool, recordToFree);1271}1272osrFrame->monitorEnterRecords = NULL;1273osrFrame = (J9OSRFrame*)((U_8*)osrFrame + osrFrameSize(osrFrame->method));1274numberOfFrames -= 1;1275}12761277/* Fix the OSR frame to resume at the catch point with an empty pending stack (the caught exception1278* is pushed after decompilation completes).1279*/1280osrFrame->bytecodePCOffset = getCurrentByteCodeIndexAndIsSameReceiver(metaData, inlineMap, inlinedCallSite, NULL);1281Trc_Decomp_jitInterpreterPCFromWalkState_Entry(jitPC);1282Trc_Decomp_jitInterpreterPCFromWalkState_exHandler(osrFrame->bytecodePCOffset);1283osrFrame->pendingStackHeight = 0;12841285performDecompile(currentThread, &decompileState, decompRecord, osrFrame, numberOfFrames);12861287freeDecompilationRecord(currentThread, decompRecord, TRUE);12881289/* Push the exception */1290UDATA *sp = currentThread->sp - 1;1291*(j9object_t*)sp = exception;1292currentThread->sp = sp;1293dumpStack(currentThread, "after jitDecompileAtExceptionCatch");1294currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(executeCurrentBytecodeFromJIT);12951296Trc_Decomp_DecompileAtExceptionCatch_Exit(currentThread, currentThread->sp, currentThread->literals, currentThread->pc);1297}12981299#if (defined(J9VM_INTERP_HOT_CODE_REPLACEMENT)) /* priv. proto (autogen) */13001301void1302jitDecompileMethodForFramePop(J9VMThread * currentThread, UDATA skipCount)1303{1304J9JITDecompileState decompileState;1305J9StackWalkState walkState;1306J9JITDecompilationInfo * decompRecord = currentThread->decompilationStack;1307J9JavaVM *vm = currentThread->javaVM;1308J9OSRBuffer *osrBuffer = &decompRecord->osrBuffer;1309UDATA numberOfFrames = osrBuffer->numberOfFrames;1310J9OSRFrame *osrFrame = (J9OSRFrame*)(osrBuffer + 1);13111312Trc_Decomp_DecompileMethodForFramePop_Entry(currentThread, decompRecord->pc);13131314/* Unstack the decomp record and fix the stacked PC */13151316*(decompRecord->pcAddress) = decompRecord->pc;1317currentThread->decompilationStack = decompRecord->next;13181319/* Collect the required information from the stack */13201321walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_MAINTAIN_REGISTER_MAP;1322walkState.skipCount = skipCount;1323walkState.frameWalkFunction = decompileMethodFrameIterator;1324walkState.walkThread = currentThread;1325walkState.userData1 = &decompileState;1326walkState.userData2 = NULL;1327currentThread->javaVM->walkStackFrames(currentThread, &walkState);13281329/* Now decompile the frame */13301331performDecompile(currentThread, &decompileState, decompRecord, osrFrame, numberOfFrames);1332freeDecompilationRecord(currentThread, decompRecord, TRUE);13331334dumpStack(currentThread, "after jitDecompileMethodForFramePop");13351336Trc_Decomp_DecompileMethodForFramePop_Exit(currentThread);1337}13381339#endif /* J9VM_INTERP_HOT_CODE_REPLACEMENT (autogen) */134013411342static J9JITDecompilationInfo *1343deleteDecompilationForExistingFrame(J9VMThread * decompileThread, J9JITDecompilationInfo * info)1344{1345PORT_ACCESS_FROM_VMC(decompileThread);1346J9JITDecompilationInfo * next = info->next;13471348Trc_Decomp_deleteDecompilationForExistingFrame_Entry();13491350*(info->pcAddress) = info->pc;13511352Trc_Decomp_deleteDecompilationForExistingFrame_freeDecomp(info, info->bp);13531354freeDecompilationRecord(decompileThread, info, FALSE);13551356Trc_Decomp_deleteDecompilationForExistingFrame_Exit();13571358return next;1359}136013611362static void1363freeDecompilationRecord(J9VMThread * decompileThread, J9JITDecompilationInfo * info, UDATA retain)1364{1365PORT_ACCESS_FROM_VMC(decompileThread);13661367j9mem_free_memory(decompileThread->lastDecompilation);1368decompileThread->lastDecompilation = NULL;1369if (info->reason & JITDECOMP_OSR_GLOBAL_BUFFER_USED) {1370omrthread_monitor_exit(decompileThread->javaVM->osrGlobalBufferLock);1371} else {1372if (retain) {1373decompileThread->lastDecompilation = info;1374} else {1375j9mem_free_memory(info);1376}1377}1378}137913801381void1382jitDataBreakpointAdded(J9VMThread * currentThread)1383{1384J9JavaVM *vm = currentThread->javaVM;1385J9JITConfig *jitConfig = vm->jitConfig;13861387/* We have exclusive */13881389Trc_Decomp_jitDataBreakpointAdded_Entry(currentThread);13901391++(jitConfig->dataBreakpointCount);13921393/* In normal mode (where the JIT does not generate code to trigger field watch events), every addition1394* of a watch must discard all compiled code. In the new mode where the JIT does generate watch triggers,1395* Only the addition of the first watch requires discarding compiled code. From then on, the JIT will1396* generate the appropriate code, so no discarding is required. See jitDataBreakpointAdded regarding1397* transitioning back out of this mode.1398*/1399bool inlineWatches = J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_JIT_INLINE_WATCHES);1400if (!inlineWatches || !jitConfig->inlineFieldWatches) {1401/* Remove all breakpoints before resetting the methods */14021403removeAllBreakpoints(currentThread);14041405/* Toss the compilation queue */14061407if (inlineWatches) {1408jitConfig->jitFlushCompilationQueue(currentThread, J9FlushCompQueueDataBreakpoint);1409/* Make all future compilations inline the field watch code */1410jitConfig->inlineFieldWatches = TRUE;1411} else {1412jitConfig->jitClassesRedefined(currentThread, 0, NULL, 0);1413}14141415/* Find every method which has been translated and mark it for retranslation */14161417jitResetAllMethods(currentThread);14181419/* Reinstall the breakpoints */14201421reinstallAllBreakpoints(currentThread);14221423/* Mark every JIT method in every stack for decompilation */14241425decompileAllMethodsInAllStacks(currentThread, JITDECOMP_DATA_BREAKPOINT);1426}14271428Trc_Decomp_jitDataBreakpointAdded_Exit(currentThread);1429}143014311432void1433jitDataBreakpointRemoved(J9VMThread * currentThread)1434{1435J9JavaVM *vm = currentThread->javaVM;14361437/* We have exclusive */14381439Trc_Decomp_jitDataBreakpointRemoved_Entry(currentThread);14401441--(vm->jitConfig->dataBreakpointCount);14421443/* For now, once the JIT is in field watch mode, it stays that way forever, even if all current1444* watches are removed. This may change in the future.1445*/1446if (J9_ARE_NO_BITS_SET(vm->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_JIT_INLINE_WATCHES)) {1447/* Remove all breakpoints before resetting the methods */14481449removeAllBreakpoints(currentThread);14501451/* Find every method which has been prevented from being translated and mark it for retranslation */14521453jitResetAllUntranslateableMethods(currentThread);14541455/* Reinstall the breakpoints */14561457reinstallAllBreakpoints(currentThread);1458}14591460Trc_Decomp_jitDataBreakpointRemoved_Exit(currentThread);1461}146214631464static void1465decompileAllMethodsInAllStacks(J9VMThread * currentThread, UDATA reason)1466{1467J9VMThread * loopThread;14681469/* Mark every JIT method in every stack for decompilation */14701471loopThread = currentThread;1472do {1473J9StackWalkState walkState;14741475walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_MAINTAIN_REGISTER_MAP;1476walkState.skipCount = 0;1477walkState.frameWalkFunction = decompileAllFrameIterator;1478walkState.walkThread = loopThread;1479walkState.userData1 = (void *) reason;1480currentThread->javaVM->walkStackFrames(currentThread, &walkState);1481} while ((loopThread = loopThread->linkNext) != currentThread);1482}148314841485static UDATA1486decompileAllFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState)1487{1488/* Decompile all JIT frames */14891490if (walkState->jitInfo) {1491addDecompilation(currentThread, walkState, (UDATA) walkState->userData1);1492}14931494return J9_STACKWALK_KEEP_ITERATING;1495}149614971498static void1499deleteAllDecompilations(J9VMThread * currentThread, UDATA reason, J9Method * method)1500{1501J9VMThread * loopThread;15021503Trc_Decomp_deleteAllDecompilations_Entry(currentThread);15041505loopThread = currentThread;1506do {1507J9JITDecompilationInfo ** previous;1508J9JITDecompilationInfo * current;15091510previous = &(loopThread->decompilationStack);1511while ((current = *previous) != NULL) {1512if ((current->reason & reason) && (!method || (current->method == method))) {1513current->reason &= ~reason;1514if (current->reason) {1515Trc_Decomp_deleteAllDecompilations_notFreeingRecord(currentThread, current, current->reason);1516previous = &(current->next);1517} else {1518*previous = deleteDecompilationForExistingFrame(loopThread, current);1519}1520} else {1521previous = &(current->next);1522}1523}1524} while ((loopThread = loopThread->linkNext) != currentThread);15251526Trc_Decomp_deleteAllDecompilations_Exit(currentThread);1527}152815291530void1531jitExceptionCaught(J9VMThread * currentThread)1532{1533J9StackWalkState * walkState = currentThread->stackWalkState;15341535Trc_Decomp_jitExceptionCaught_Entry(currentThread, walkState->arg0EA);15361537/* Called when an exception is caught, the thread's walkState knows how far to pop */15381539J9JITDecompilationInfo *catchDecompile = jitCleanUpDecompilationStack(currentThread, walkState, FALSE);1540void *handlerPC = walkState->userData2;15411542/* If the catch frame is not JIT, nothing more needs to be done */15431544if (!walkState->jitInfo) {1545Trc_Decomp_jitExceptionCaught_notJITFrame(currentThread);1546return;1547}15481549/* userData4 indicates whether or not the handler is synthetic */1550if (NULL != walkState->userData4) {1551/* The exception handler has been inserted by the JIT in order to exit the monitor1552* for an inlined synchronized method - do not report the exception catch event or1553* attempt to decompile at this point. The handler will rethrow the exception after1554* the monitor exit and the catch will be reported when the real catch block that came1555* from the bytecodes is reached.1556*/1557Trc_Decomp_jitExceptionCaught_SyntheticHandler(currentThread);1558} else {1559Trc_Decomp_jitExceptionCaught_JITFrame(currentThread);15601561/* If a decompilation record exists for the catch frame, update the PC to be the exception handler PC */15621563if (NULL != catchDecompile) {1564Trc_Decomp_jitExceptionCaught_frameMarked(currentThread, walkState->bp);1565catchDecompile->pc = (U_8 *)handlerPC;1566}15671568/* Report the exception catch event if hooked */15691570if (J9_EVENT_IS_HOOKED(currentThread->javaVM->hookInterface, J9HOOK_VM_EXCEPTION_CATCH)) {1571Trc_Decomp_jitExceptionCaught_mustReportNormal(currentThread, walkState->arg0EA);15721573if (catchDecompile) {1574Trc_Decomp_jitExceptionCaught_decompileRequested(currentThread);1575currentThread->floatTemp4 = J9_BUILDER_SYMBOL(jitDecompileAtExceptionCatch);1576} else {1577Trc_Decomp_jitExceptionCaught_notDecompiling(currentThread);1578currentThread->floatTemp4 = handlerPC;1579}1580walkState->userData2 = J9_BUILDER_SYMBOL(jitReportExceptionCatch);1581} else {1582Trc_Decomp_jitExceptionCaught_notReportingCatch(currentThread);1583if (catchDecompile) {1584Trc_Decomp_jitExceptionCaught_decompileRequested(currentThread);1585walkState->userData2 = J9_BUILDER_SYMBOL(jitDecompileAtExceptionCatch);1586} else {1587Trc_Decomp_jitExceptionCaught_notDecompiling(currentThread);1588}1589}1590}15911592Trc_Decomp_jitExceptionCaught_Exit(currentThread);1593}159415951596static void1597markMethodBreakpointed(J9VMThread * currentThread, J9JITBreakpointedMethod * breakpointedMethod)1598{1599J9Method * method = breakpointedMethod->method;1600void * extra = method->extra;16011602breakpointedMethod->hasBeenTranslated = FALSE;1603if ((((UDATA) extra) & J9_STARTPC_NOT_TRANSLATED) == 0) {1604breakpointedMethod->hasBeenTranslated = TRUE;1605_fsdSwitchToInterpPatchEntry(extra);1606}16071608method->constantPool = (J9ConstantPool *) ((UDATA) method->constantPool | (UDATA)J9_STARTPC_METHOD_BREAKPOINTED);1609if (NULL != currentThread->javaVM->jitConfig->jitMethodBreakpointed) { // TODO: remove once JIT is updated1610currentThread->javaVM->jitConfig->jitMethodBreakpointed(currentThread, method);1611}1612}161316141615static void1616markMethodUnbreakpointed(J9VMThread * currentThread, J9JITBreakpointedMethod * breakpointedMethod)1617{1618J9Method * method = breakpointedMethod->method;16191620method->constantPool = (J9ConstantPool *) ((UDATA) method->constantPool & ~(UDATA)J9_STARTPC_METHOD_BREAKPOINTED);1621if (breakpointedMethod->hasBeenTranslated) {1622_fsdRestoreToJITPatchEntry(method->extra);1623}1624if (NULL != currentThread->javaVM->jitConfig->jitMethodUnbreakpointed) { // TODO: remove once JIT is updated1625currentThread->javaVM->jitConfig->jitMethodUnbreakpointed(currentThread, method);1626}1627}162816291630static void1631removeAllBreakpoints(J9VMThread * currentThread)1632{1633J9JITBreakpointedMethod * breakpointedMethod = currentThread->javaVM->jitConfig->breakpointedMethods;16341635while (breakpointedMethod) {1636markMethodUnbreakpointed(currentThread, breakpointedMethod);1637breakpointedMethod = breakpointedMethod->link;1638}1639}164016411642static void1643reinstallAllBreakpoints(J9VMThread * currentThread)1644{1645J9JITBreakpointedMethod * breakpointedMethod = currentThread->javaVM->jitConfig->breakpointedMethods;16461647while (breakpointedMethod) {1648markMethodBreakpointed(currentThread, breakpointedMethod);1649breakpointedMethod = breakpointedMethod->link;1650}1651}165216531654void1655jitSingleStepAdded(J9VMThread * currentThread)1656{1657/* We have exclusive */16581659Trc_Decomp_jitSingleStepAdded_Entry(currentThread);16601661if (++(currentThread->javaVM->jitConfig->singleStepCount) == 1) {16621663/* Mark every JIT method in every stack for decompilation */16641665decompileAllMethodsInAllStacks(currentThread, JITDECOMP_SINGLE_STEP);1666}16671668Trc_Decomp_jitSingleStepAdded_Exit(currentThread);1669}167016711672void1673jitSingleStepRemoved(J9VMThread * currentThread)1674{1675/* We have exclusive */16761677Trc_Decomp_jitSingleStepRemoved_Entry(currentThread);16781679if (--(currentThread->javaVM->jitConfig->singleStepCount) == 0) {16801681/* Remove the single step decompilations */16821683deleteAllDecompilations(currentThread, JITDECOMP_SINGLE_STEP, NULL);1684}16851686Trc_Decomp_jitSingleStepRemoved_Exit(currentThread);1687}168816891690UDATA1691initializeFSD(J9JavaVM * vm)1692{1693J9JITConfig * jitConfig = vm->jitConfig;16941695jitConfig->jitCodeBreakpointAdded = jitCodeBreakpointAdded;1696jitConfig->jitCodeBreakpointRemoved = jitCodeBreakpointRemoved;1697jitConfig->jitDataBreakpointAdded = jitDataBreakpointAdded;1698jitConfig->jitDataBreakpointRemoved = jitDataBreakpointRemoved;1699jitConfig->jitSingleStepAdded = jitSingleStepAdded;1700jitConfig->jitSingleStepRemoved = jitSingleStepRemoved;1701jitConfig->jitExceptionCaught = jitExceptionCaught;1702jitConfig->jitCleanUpDecompilationStack = jitCleanUpDecompilationStack;1703#ifdef J9VM_INTERP_HOT_CODE_REPLACEMENT1704jitConfig->jitHotswapOccurred = jitHotswapOccurred;1705jitConfig->jitDecompileMethodForFramePop = jitDecompileMethodForFramePop;1706#endif1707#ifdef J9VM_OPT_JVMTI1708jitConfig->jitFramePopNotificationAdded = jitFramePopNotificationAdded;1709#endif1710jitConfig->jitStackLocalsModified = jitStackLocalsModified;1711jitConfig->jitLocalSlotAddress = jitLocalSlotAddress;1712jitConfig->jitAddDecompilationForFramePop = jitAddDecompilationForFramePop;17131714jitConfig->fsdEnabled = TRUE;17151716return 0;1717}17181719static J9OSRFrame *1720findOSRFrameAtInlineDepth(J9OSRBuffer *osrBuffer, UDATA inlineDepth)1721{1722J9OSRFrame *osrFrame = (J9OSRFrame*)(osrBuffer + 1);1723UDATA osrFrameInlineDepth = osrBuffer->numberOfFrames - 1;1724Assert_CodertVM_true(osrFrameInlineDepth >= inlineDepth);1725while (osrFrameInlineDepth != inlineDepth) {1726osrFrame = (J9OSRFrame*)((U_8*)osrFrame + osrFrameSize(osrFrame->method));1727osrFrameInlineDepth -= 1;1728}1729return osrFrame;1730}17311732#if (defined(J9VM_OPT_JVMTI)) /* priv. proto (autogen) */17331734static void1735jitFramePopNotificationAdded(J9VMThread * currentThread, J9StackWalkState * walkState, UDATA inlineDepth)1736{1737J9JITDecompilationInfo *decompilationInfo = NULL;17381739Trc_Decomp_jitFramePopNotificationAdded_Entry(currentThread, walkState->walkThread, walkState->arg0EA, walkState->method);1740decompPrintMethod(currentThread, walkState->method);17411742decompilationInfo = addDecompilation(currentThread, walkState, JITDECOMP_FRAME_POP_NOTIFICATION);1743if (NULL != decompilationInfo) {1744J9OSRFrame *osrFrame = findOSRFrameAtInlineDepth(&decompilationInfo->osrBuffer, inlineDepth);1745osrFrame->flags |= J9OSRFRAME_NOTIFY_FRAME_POP;1746}17471748Trc_Decomp_jitFramePopNotificationAdded_Exit(currentThread);1749}1750#endif /* J9VM_OPT_JVMTI (autogen) */17511752static J9JITDecompilationInfo*1753jitAddDecompilationForFramePop(J9VMThread * currentThread, J9StackWalkState * walkState)1754{1755return addDecompilation(currentThread, walkState, JITDECOMP_POP_FRAMES);1756}175717581759void1760jitStackLocalsModified(J9VMThread * currentThread, J9StackWalkState * walkState)1761{1762Trc_Decomp_jitStackLocalsModified_Entry(currentThread);17631764if (walkState->jitInfo == NULL) {1765Trc_Decomp_jitStackLocalsModified_notJIT(currentThread);1766} else {1767addDecompilation(currentThread, walkState, JITDECOMP_STACK_LOCALS_MODIFIED);1768}17691770Trc_Decomp_jitStackLocalsModified_Exit(currentThread);1771}177217731774void1775jitBreakpointedMethodCompiled(J9VMThread * currentThread, J9Method * method, void * startAddress)1776{1777J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;1778J9JITBreakpointedMethod * breakpointedMethod = jitConfig->breakpointedMethods;17791780Trc_Decomp_jitBreakpointedMethodCompiled_Entry(currentThread, method, startAddress);1781decompPrintMethod(currentThread, method);17821783while (breakpointedMethod) {1784if (breakpointedMethod->method == method) {1785/* Assert breakpointedMethod->hasBeenTranslated == FALSE */1786breakpointedMethod->hasBeenTranslated = TRUE;1787_fsdSwitchToInterpPatchEntry(startAddress);1788Trc_Decomp_jitBreakpointedMethodCompiled_Exit_success(currentThread, breakpointedMethod);1789return;1790}1791breakpointedMethod = breakpointedMethod->link;1792}1793Trc_Decomp_jitBreakpointedMethodCompiled_Exit_fail(currentThread);1794}179517961797/**1798* Compute the number of bytes required for a single OSR frame.1799*1800* @param[in] *method the J9Method for which to compute the OSR frame size1801*1802* @return byte size of the OSR frame1803*/1804UDATA1805osrFrameSize(J9Method *method)1806{1807J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);1808return osrFrameSizeRomMethod(romMethod);1809}181018111812/**1813* Compute the number of bytes required for a single OSR frame.1814*1815* @param[in] *romMethod the J9ROMMethod for which to compute the OSR frame size1816*1817* @return byte size of the OSR frame1818*/1819UDATA1820osrFrameSizeRomMethod(J9ROMMethod *romMethod)1821{1822U_32 numberOfLocals = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod) + J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod);1823U_32 maxStack = J9_MAX_STACK_FROM_ROM_METHOD(romMethod);18241825/* Adjust the number of locals to account for any hidden slots */1826if ((romMethod->modifiers & J9AccSynchronized) || (J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod))) {1827numberOfLocals += 1;1828}18291830/* Account for the fixed size structure and each UDATA slot required */18311832return sizeof(J9OSRFrame) + (sizeof(UDATA) * (maxStack + numberOfLocals));1833}183418351836/**1837* Compute the number of bytes required for all OSR frames in the buffer1838* representing the stack information at the current method in the walk state.1839*1840* @param[in] *currentThread the current J9VMThread1841* @param[in] *metaData the JIT metadata for the compilation1842* @param[in] *jitPC the compiled PC at which to decompile1843* @param[in] resolveFrameFlags the flags from the previous resolve frame (0 if no resolve frame)1844*1845* @return byte size of the OSR frames1846*/1847static UDATA1848osrAllFramesSize(J9VMThread *currentThread, J9JITExceptionTable *metaData, void *jitPC, UDATA resolveFrameFlags)1849{1850UDATA totalSize = 0;1851void * stackMap = NULL;1852void * inlineMap = NULL;18531854/* Count the inlined methods */1855jitGetMapsFromPC(currentThread, currentThread->javaVM, metaData, (UDATA)jitPC, &stackMap, &inlineMap);1856Assert_CodertVM_false(NULL == inlineMap);1857if (NULL != getJitInlinedCallInfo(metaData)) {1858void *inlinedCallSite = getFirstInlinedCallSite(metaData, inlineMap);1859if (inlinedCallSite != NULL) {1860UDATA inlineDepth = getJitInlineDepthFromCallSite(metaData, inlinedCallSite);1861do {1862J9Method * inlinedMethod = (J9Method *)getInlinedMethod(inlinedCallSite);1863totalSize += osrFrameSize(inlinedMethod);1864inlinedCallSite = getNextInlinedCallSite(metaData, inlinedCallSite);1865inlineDepth -= 1;1866} while (0 != inlineDepth);1867}1868}18691870/* Count the outer method */1871totalSize += osrFrameSize(metaData->ramMethod);18721873return totalSize;1874}187518761877/**1878* Perform an OSR (fill in the OSR buffer) for the frame represented in the stack walk state.1879*1880* Note that the JITted stack frame will be copied to (osrScratchBuffer + osrScratchBufferSize).1881* This function assumes that the buffer has been allocated large enough.1882*1883* @param[in] *currentThread current thread1884* @param[in] *walkState stack walk state (already at the OSR point)1885* @param[in] *osrBuffer pointer to correctly-allocated OSR buffer1886* @param[in] *osrScratchBuffer pointer to scratch buffer1887* @param[in] osrScratchBufferSize size of the scratch buffer1888* @param[in] jitStackFrameSize the number of bytes in the JITted stack frame1889* @param[out] mustDecompile if non-NULL, set to TRUE or FALSE to indicate if the OSR has performed a destructive action1890*1891* @return an OSR result code1892*/1893static UDATA1894performOSR(J9VMThread *currentThread, J9StackWalkState *walkState, J9OSRBuffer *osrBuffer, U_8 *osrScratchBuffer, UDATA scratchBufferSize, UDATA jitStackFrameSize, UDATA *mustDecompile)1895{1896J9JavaVM *vm = currentThread->javaVM;1897PORT_ACCESS_FROM_JAVAVM(vm);1898J9VMThread *targetThread = walkState->walkThread;1899J9JITExceptionTable *metaData = walkState->jitInfo;1900void *pc = walkState->pc;1901void *osrBlock = NULL;1902UDATA result = OSR_OK;1903UDATA forceDecompile = FALSE;1904UDATA *osrJittedFrameCopy = (UDATA*)(osrScratchBuffer + scratchBufferSize);19051906/* Assert that this frame has been compiled using OSR */1907Assert_CodertVM_true(usesOSR(currentThread, metaData));19081909/* Assert that the live registers have been tracked */1910Assert_CodertVM_true(walkState->flags & J9_STACKWALK_MAINTAIN_REGISTER_MAP);19111912/* Copy the stack frame after the scratch buffer (assume it's been allocated correctly).1913* Assert the number of bytes provided matches the expected frame size from the metadata1914* (arguments + return address + totalFrameSize slots).1915*/1916Assert_CodertVM_true(jitStackFrameSize == ((J9_ARG_COUNT_FROM_ROM_METHOD(J9_ROM_METHOD_FROM_RAM_METHOD(metaData->ramMethod)) + 1 + metaData->totalFrameSize) * sizeof(UDATA)));1917memcpy(osrJittedFrameCopy, walkState->unwindSP, jitStackFrameSize);19181919/* Perform the OSR */1920osrBlock = preOSR(currentThread, metaData, pc);1921/* Ensure the OSR block is within either the warm or cold region of the compilation */1922Assert_CodertVM_true(1923(((UDATA)osrBlock > metaData->startPC) && ((UDATA)osrBlock < metaData->endWarmPC)) ||1924((0 != metaData->startColdPC) && (((UDATA)osrBlock >= metaData->startColdPC) && ((UDATA)osrBlock < metaData->endPC)))1925);1926currentThread->osrBuffer = osrBuffer;1927currentThread->osrScratchBuffer = osrScratchBuffer;1928currentThread->osrJittedFrameCopy = osrJittedFrameCopy;1929currentThread->osrFrameIndex = sizeof(J9OSRBuffer);1930currentThread->privateFlags |= J9_PRIVATE_FLAGS_OSR_IN_PROGRESS;1931currentThread->javaVM->internalVMFunctions->jitFillOSRBuffer(currentThread, osrBlock);1932currentThread->privateFlags &= ~J9_PRIVATE_FLAGS_OSR_IN_PROGRESS;1933currentThread->osrBuffer = NULL;1934currentThread->osrJittedFrameCopy = NULL;1935if (0 != postOSR(currentThread, metaData, pc)) {1936forceDecompile = TRUE;1937}19381939if (NULL != mustDecompile) {1940*mustDecompile = forceDecompile;1941}1942return result;1943}194419451946/**1947* Find the address of a local variable slot for a compiled method. Requires that the target frame1948* be compiled with either FSD or OSR (or both).1949*1950* @param[in] *currentThread current thread1951* @param[in] *walkState stack walk state (already at the OSR point)1952* @param[in] slot the slot number to query1953* @param[in] inlineDepth the inline depth of the frame being queried1954*1955* @return the address of the local slot, NULL if a native out of memory occurs1956*/1957static UDATA *1958jitLocalSlotAddress(J9VMThread * currentThread, J9StackWalkState *walkState, UDATA slot, UDATA inlineDepth)1959{1960J9JITExceptionTable *metaData = walkState->jitInfo;1961UDATA *slotAddress = NULL;19621963/* If this frame has been OSR-compiled, add a decompilation record (to perform the OSR) and return a pointer1964* into the appropriate frame in the buffer.1965*/1966if (usesOSR(currentThread, metaData)) {1967J9JITDecompilationInfo *decompilationInfo = addDecompilation(currentThread, walkState, 0);19681969if (NULL != decompilationInfo) {1970J9OSRBuffer *osrBuffer = &decompilationInfo->osrBuffer;1971J9OSRFrame *osrFrame = (J9OSRFrame*)(osrBuffer + 1);1972UDATA osrFrameInlineDepth = osrBuffer->numberOfFrames - 1;1973while (osrFrameInlineDepth != inlineDepth) {1974osrFrame = (J9OSRFrame*)((U_8*)osrFrame + osrFrameSize(osrFrame->method));1975osrFrameInlineDepth -= 1;1976}1977slotAddress = ((UDATA*)(osrFrame + 1)) + osrFrame->maxStack + osrFrame->numberOfLocals - 1 - slot;1978}1979} else {1980J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method);19811982/* OSR not in use in this frame - look up the stack slot using the FSD metadata */19831984Assert_CodertVM_true(0 == inlineDepth);1985if (slot >= romMethod->argCount) {1986J9JITStackAtlas * stackAtlas = (J9JITStackAtlas *) (metaData->gcStackAtlas);19871988slotAddress = (UDATA *) (((UDATA) walkState->bp) + stackAtlas->localBaseOffset);1989if (romMethod->modifiers & J9AccSynchronized) {1990/* Synchronized methods have one hidden temp to hold the sync object */1991++slotAddress;1992} else if (J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod)) {1993/* Non-empty java.lang.Object.<init> has one hidden temp to hold a copy of the receiver */1994++slotAddress;1995}1996slotAddress += metaData->tempOffset; /* skip pending push area */1997slotAddress += ((romMethod->tempCount - 1) - (slot - romMethod->argCount));1998} else {1999slotAddress = walkState->arg0EA - slot;2000}2001}20022003return slotAddress;2004}200520062007/**2008* Compute the required size of the OSR scratch buffer.2009*2010* @param[in] *currentThread current thread2011* @param[in] *metadata JIT metadata for this compilation2012* @param[in] *jitPC compiled PC at which to OSR2013*2014* @return the scratch buffer size2015*/2016static UDATA2017roundedOSRScratchBufferSize(J9VMThread * currentThread, J9JITExceptionTable *metaData, void *jitPC)2018{2019J9JavaVM *vm = currentThread->javaVM;2020UDATA scratchBufferSize = osrScratchBufferSize(currentThread, metaData, jitPC);20212022/* Ensure a minimum size for the scratch buffer to allow for possible calls while the stack is active2023* (in particular, Linux on x86 performs a call in order to compute the GOT). Currently, the minimum2024* size is 8 UDATAs. Round the size of the scratch buffer up to UDATA.2025*/2026scratchBufferSize = OMR_MAX(scratchBufferSize, (8 * sizeof(UDATA)));2027scratchBufferSize = ROUND_TO(sizeof(UDATA), scratchBufferSize);2028return scratchBufferSize;2029}203020312032/**2033* Determine the address of an numbered object slot in a compiled stack frame.2034*2035* @param[in] *osrData the OSR data block2036* @param[in] slot the slot index, numbered from 02037*2038* @return the address of the object slot in the compiled stack frame2039*/2040static j9object_t*2041getObjectSlotAddress(J9OSRData *osrData, U_16 slot)2042{2043UDATA *slotAddress = NULL;2044U_16 numParms = getJitNumberOfParmSlots(osrData->gcStackAtlas);20452046/* The base address depends on the range of the slot index */2047if (slot < numParms) {2048slotAddress = osrData->objectArgScanCursor;2049} else {2050slotAddress = osrData->objectTempScanCursor;2051slot -= numParms;2052}2053slotAddress += slot;2054return (j9object_t*)slotAddress;2055}205620572058/**2059* Create a monitor enter record for each object locked in the OSR frame. The records are linked2060* together and stored in the J9OSRFrame.2061*2062* @param[in] *currentThread current thread2063* @param[in] *osrData the OSR data block2064*2065* @return an OSR result code2066*/2067static UDATA2068createMonitorEnterRecords(J9VMThread *currentThread, J9OSRData *osrData)2069{2070UDATA result = OSR_OK;2071J9Pool *monitorEnterRecordPool = osrData->targetThread->monitorEnterRecordPool;2072if (NULL != monitorEnterRecordPool) {2073J9JITStackAtlas *gcStackAtlas = osrData->gcStackAtlas;2074void *inlinedCallSite = osrData->inlinedCallSite;2075U_8 *monitorMask = getMonitorMask(gcStackAtlas, inlinedCallSite);2076if (NULL != monitorMask) {2077J9MonitorEnterRecord listHead;2078J9MonitorEnterRecord *lastEnterRecord = &listHead;2079U_8 *liveMonitorMap = osrData->liveMonitorMap;2080U_16 numberOfMapBits = osrData->numberOfMapBits;2081U_16 i = 0;2082listHead.next = NULL;2083for (i = 0; i < numberOfMapBits; ++i) {2084U_8 bit = liveMonitorMap[i >> 3] & monitorMask[i >> 3] & (1 << (i & 7));2085if (0 != bit) {2086J9MonitorEnterRecord *newEnterRecord = NULL;2087j9object_t object = *getObjectSlotAddress(osrData, i);2088/* Assert that the mapped object is not stack-allocated */2089Assert_CodertVM_false(NULL == object);2090newEnterRecord = (J9MonitorEnterRecord*)pool_newElement(monitorEnterRecordPool);2091if (NULL == newEnterRecord) {2092/* Discard any records created up to this point */2093J9MonitorEnterRecord *freeRecord = listHead.next;2094while (NULL != freeRecord) {2095J9MonitorEnterRecord *nextRecord = freeRecord->next;2096pool_removeElement(monitorEnterRecordPool, freeRecord);2097freeRecord = nextRecord;2098}2099result = OSR_OUT_OF_MEMORY;2100break;2101}2102lastEnterRecord->next = newEnterRecord;2103lastEnterRecord = newEnterRecord;2104newEnterRecord->object = object;2105newEnterRecord->dropEnterCount = 1;2106newEnterRecord->arg0EA = NULL;2107newEnterRecord->next = NULL;2108}2109}2110osrData->osrFrame->monitorEnterRecords = listHead.next;2111}2112}2113return result;2114}211521162117/**2118* Initialize an OSR frame.2119*2120* @param[in] *currentThread the current J9VMThread2121* @param[in] *osrData the OSR data block2122*2123* @return an OSR result code2124*/2125static UDATA2126initializeOSRFrame(J9VMThread *currentThread, J9OSRData *osrData)2127{2128UDATA result = OSR_OK;2129J9OSRFrame *osrFrame = osrData->osrFrame;2130J9JITExceptionTable *metaData = osrData->metaData;2131void *inlineMap = osrData->inlineMap;2132void *inlinedCallSite = osrData->inlinedCallSite;2133J9Method *method = osrData->method;2134UDATA resolveFrameFlags = osrData->resolveFrameFlags;2135UDATA bytecodePCOffset = getCurrentByteCodeIndexAndIsSameReceiver(metaData, inlineMap, inlinedCallSite, NULL);2136U_8 *bytecodePC = J9_BYTECODE_START_FROM_RAM_METHOD(method) + bytecodePCOffset;2137UDATA pendingStackHeight = getPendingStackHeight(currentThread, bytecodePC, method, resolveFrameFlags);2138J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);2139U_8 argCount = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod);2140U_32 numberOfLocals = argCount + J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod);2141U_32 maxStack = J9_MAX_STACK_FROM_ROM_METHOD(romMethod);21422143Trc_Decomp_jitInterpreterPCFromWalkState_Entry(osrData->jitPC);2144Trc_Decomp_jitInterpreterPCFromWalkState_stackMap(bytecodePC);21452146/* Create monitor enter records */2147if (NULL != osrData->liveMonitorMap) {2148result = createMonitorEnterRecords(currentThread, osrData);2149if (OSR_OK != result) {2150goto done;2151}2152}2153/* Adjust the number of locals to account for any hidden slots */2154if ((romMethod->modifiers & J9AccSynchronized) || (J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod))) {2155numberOfLocals += 1;2156}2157osrFrame->method = method;2158osrFrame->bytecodePCOffset = bytecodePC - J9_BYTECODE_START_FROM_RAM_METHOD(method);2159osrFrame->numberOfLocals = numberOfLocals;2160osrFrame->maxStack = maxStack;2161osrFrame->pendingStackHeight = pendingStackHeight;2162/* Move to the next frame */2163osrData->osrFrame = (J9OSRFrame*)(((UDATA*)(osrFrame + 1)) + maxStack + numberOfLocals);2164done:2165return result;2166}216721682169/**2170* Initialize the OSR buffer and frames.2171*2172* @param[in] *currentThread current thread2173* @param[in] *osrBuffer OSR buffer2174* @param[in] *osrData the OSR data block2175*/2176static UDATA2177initializeOSRBuffer(J9VMThread *currentThread, J9OSRBuffer *osrBuffer, J9OSRData *osrData)2178{2179UDATA result = OSR_OK;2180J9JITExceptionTable *metaData = osrData->metaData;2181void *jitPC = osrData->jitPC;2182UDATA resolveFrameFlags = osrData->resolveFrameFlags;2183UDATA numberOfFrames = 1; /* count the outer method now */2184J9Method *outerMethod = metaData->ramMethod;2185void *stackMap = NULL;2186void *inlineMap = NULL;2187J9JITStackAtlas *gcStackAtlas = NULL;2188U_8 *liveMonitorMap = NULL;2189U_16 numberOfMapBits = 0;21902191/* Get the stack map, inline map and live monitor metadata */2192jitGetMapsFromPC(currentThread, currentThread->javaVM, metaData, (UDATA)jitPC, &stackMap, &inlineMap);2193liveMonitorMap = getJitLiveMonitors(metaData, stackMap);2194gcStackAtlas = (J9JITStackAtlas *)getJitGCStackAtlas(metaData);2195numberOfMapBits = getJitNumberOfMapBytes(gcStackAtlas) << 3;2196osrData->gcStackAtlas = gcStackAtlas;2197osrData->liveMonitorMap = liveMonitorMap;2198osrData->numberOfMapBits = numberOfMapBits;2199osrData->inlineMap = inlineMap;2200osrData->osrFrame = (J9OSRFrame*)(osrBuffer + 1);22012202/* Fill in the data for the inlined methods */2203Assert_CodertVM_false(NULL == inlineMap);2204if (NULL != getJitInlinedCallInfo(metaData)) {2205void *inlinedCallSite = getFirstInlinedCallSite(metaData, inlineMap);2206if (inlinedCallSite != NULL) {2207UDATA inlineDepth = getJitInlineDepthFromCallSite(metaData, inlinedCallSite);2208numberOfFrames += inlineDepth;2209do {2210J9Method *inlinedMethod = (J9Method *)getInlinedMethod(inlinedCallSite);2211osrData->inlinedCallSite = inlinedCallSite;2212osrData->method = inlinedMethod;2213result = initializeOSRFrame(currentThread, osrData);2214if (OSR_OK != result) {2215goto done;2216}2217osrData->resolveFrameFlags = 0;2218inlinedCallSite = getNextInlinedCallSite(metaData, inlinedCallSite);2219inlineDepth -= 1;2220} while (0 != inlineDepth);2221Assert_CodertVM_true(NULL == inlinedCallSite);2222}2223}22242225/* Fill in the frame for the outer method */2226osrData->inlinedCallSite = NULL;2227osrData->method = outerMethod;2228result = initializeOSRFrame(currentThread, osrData);2229if (OSR_OK != result) {2230goto done;2231}22322233/* Fill in the OSR buffer header */2234osrBuffer->numberOfFrames = numberOfFrames;2235osrBuffer->jitPC = jitPC;2236done:2237return result;2238}223922402241/**2242* Induce OSR on the current thread.2243*2244* @param[in] *currentThread current thread2245* @param[in] *jitPC compiled PC at which to OSR2246*/2247void2248induceOSROnCurrentThread(J9VMThread * currentThread)2249{2250J9JavaVM * vm = currentThread->javaVM;2251PORT_ACCESS_FROM_JAVAVM(vm);2252J9JITExceptionTable *metaData = NULL;2253void *jitPC = NULL;2254UDATA decompRecordSize = 0;2255UDATA scratchBufferSize = 0;2256UDATA jitStackFrameSize = 0;2257UDATA totalSize = 0;2258J9JITDecompilationInfo *decompilationRecord = NULL;2259UDATA reason = JITDECOMP_ON_STACK_REPLACEMENT;2260void *osrBlock = NULL;2261U_8 *osrScratchBuffer = NULL;2262UDATA osrReturnCode = OSR_OK;2263J9StackWalkState walkState;2264J9OSRData osrData;22652266dumpStack(currentThread, "induceOSROnCurrentThread");22672268/* The stack currently has a resolve frame on top, followed by the JIT frame we2269* wish to OSR. Walk the stack down to the JIT frame to gather the data required2270* for decompilation.2271*/2272walkState.walkThread = currentThread;2273walkState.maxFrames = 2;2274walkState.flags = J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_MAINTAIN_REGISTER_MAP | J9_STACKWALK_COUNT_SPECIFIED;2275currentThread->javaVM->walkStackFrames(currentThread, &walkState);2276jitPC = walkState.pc;2277metaData = walkState.jitInfo;2278Assert_CodertVM_true(NULL != metaData);2279Assert_CodertVM_true(usesOSR(currentThread, metaData));22802281/* Determine the required sizes of:2282* a) a decompilation record (fixed size - a J9JITDecompilationInfo)2283* b) the OSR frames2284* c) the OSR scratch buffer2285* d) the copy of the stack frame being OSRed2286*/2287decompRecordSize = osrAllFramesSize(currentThread, metaData, jitPC, walkState.resolveFrameFlags);2288decompRecordSize += sizeof(J9JITDecompilationInfo);2289scratchBufferSize = roundedOSRScratchBufferSize(currentThread, metaData, jitPC);2290jitStackFrameSize = (UDATA)(walkState.arg0EA + 1) - (UDATA)walkState.unwindSP;2291totalSize = decompRecordSize + scratchBufferSize + jitStackFrameSize;2292Assert_CodertVM_true(totalSize <= vm->osrGlobalBufferSize);22932294/* Allocate the buffer, falling back to the global one if the allocation fails */2295decompilationRecord = (J9JITDecompilationInfo*)j9mem_allocate_memory(totalSize, OMRMEM_CATEGORY_JIT);2296if (NULL == decompilationRecord) {2297/* Trc_Decomp_induceOSROnCurrentThread_usingGlobalBuffer(currentThread); */2298omrthread_monitor_enter(vm->osrGlobalBufferLock);2299decompilationRecord = (J9JITDecompilationInfo*)vm->osrGlobalBuffer;2300reason |= JITDECOMP_OSR_GLOBAL_BUFFER_USED;2301}2302memset(decompilationRecord, 0, totalSize);2303decompilationRecord->usesOSR = TRUE;2304/* Trc_Decomp_addDecompilation_allocRecord(currentThread, info); */23052306/* Fill in the interpreter values in the OSR buffer */2307osrData.targetThread = currentThread;2308osrData.metaData = metaData;2309osrData.jitPC = jitPC;2310osrData.resolveFrameFlags = walkState.resolveFrameFlags;2311osrData.objectArgScanCursor = getObjectArgScanCursor(&walkState);2312osrData.objectTempScanCursor = getObjectTempScanCursor(&walkState);2313if (OSR_OK != initializeOSRBuffer(currentThread, &decompilationRecord->osrBuffer, &osrData)) {2314Trc_Decomp_addDecompilation_allocFailed(currentThread);2315goto outOfMemory;2316}23172318/* Perform the OSR to fill in the buffer. On success, add the new decompilation to the stack.2319* If the OSR fails, discard the decompilation - this will result in OutOfMemoryError being thrown.2320*/2321osrScratchBuffer = ((U_8*)decompilationRecord) + decompRecordSize;2322osrReturnCode = performOSR(currentThread, &walkState, &decompilationRecord->osrBuffer, osrScratchBuffer, scratchBufferSize, jitStackFrameSize, NULL);2323if (OSR_OK != osrReturnCode) {2324outOfMemory:2325decompilationRecord->reason = reason;2326freeDecompilationRecord(currentThread, decompilationRecord, FALSE);2327} else {2328fixStackForNewDecompilation(currentThread, &walkState, decompilationRecord, reason, ¤tThread->decompilationStack);2329}2330}23312332/**2333* Ensure that the global OSR buffer is large enough for the given2334* input sizes. If the buffer is too small, an attempt will be made2335* to grow it to the new size.2336*2337* @param[in] *vm the J9JavaVM2338* @param[in] osrFramesByteSize the size in bytes of the OSR frame data2339* @param[in] osrScratchBufferByteSize the size in bytes of the scratch buffer2340* @param[in] osrStackFrameByteSize the size in bytes of the JIT stack frame2341*2342* @return TRUE if the buffer is large enough, FALSE if it is not (and could not be grown)2343*/2344UDATA2345ensureOSRBufferSize(J9JavaVM *vm, UDATA osrFramesByteSize, UDATA osrScratchBufferByteSize, UDATA osrStackFrameByteSize)2346{2347UDATA result = TRUE;2348UDATA osrGlobalBufferSize = sizeof(J9JITDecompilationInfo);2349osrGlobalBufferSize += ROUND_TO(sizeof(UDATA), osrFramesByteSize);2350osrGlobalBufferSize += ROUND_TO(sizeof(UDATA), osrScratchBufferByteSize);2351osrGlobalBufferSize += ROUND_TO(sizeof(UDATA), osrStackFrameByteSize);2352if (osrGlobalBufferSize > vm->osrGlobalBufferSize) {2353omrthread_monitor_enter(vm->osrGlobalBufferLock);2354if (osrGlobalBufferSize > vm->osrGlobalBufferSize) {2355PORT_ACCESS_FROM_JAVAVM(vm);2356void *newBuffer = j9mem_reallocate_memory(vm->osrGlobalBuffer, osrGlobalBufferSize, OMRMEM_CATEGORY_JIT);2357if (NULL == newBuffer) {2358result = FALSE;2359} else {2360vm->osrGlobalBufferSize = osrGlobalBufferSize;2361vm->osrGlobalBuffer = newBuffer;2362}2363}2364omrthread_monitor_exit(vm->osrGlobalBufferLock);2365}2366return result;2367}23682369/* Resolve frame is already built */2370void2371c_jitDecompileAfterAllocation(J9VMThread *currentThread)2372{2373/* Allocated object stored in floatTemp1 */2374j9object_t const obj = (j9object_t)currentThread->floatTemp1;2375/* Fetch and unstack the decompilation information for this frame */23762377Trc_Decomp_DecompileAfterAllocation_Entry(currentThread, obj, currentThread->pc);23782379J9JITDecompilationInfo *decompRecord = fetchAndUnstackDecompilationInfo(currentThread);2380/* Fix the saved PC since the frame is still on the stack */2381fixSavedPC(currentThread, decompRecord);2382/* Decompile the method */2383jitDecompileMethod(currentThread, decompRecord);2384/* Push the newly-allocated object and advance the PC beyond the allocation bytecode */2385UDATA *sp = currentThread->sp - 1;2386*(j9object_t*)sp = obj;2387currentThread->sp = sp;2388currentThread->pc += (J9JavaInstructionSizeAndBranchActionTable[*currentThread->pc] & 0x7);2389dumpStack(currentThread, "after jitDecompileAfterAllocation");2390currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(executeCurrentBytecodeFromJIT);23912392Trc_Decomp_DecompileAfterAllocation_Exit(currentThread, currentThread->sp, currentThread->pc);2393}23942395/* Resolve frame is already built */2396void2397c_jitDecompileAtCurrentPC(J9VMThread *currentThread)2398{2399Trc_Decomp_DecompileAtCurrentPC_Entry(currentThread);24002401/* Fetch and unstack the decompilation information for this frame */2402J9JITDecompilationInfo *decompRecord = fetchAndUnstackDecompilationInfo(currentThread);2403/* Fix the saved PC since the frame is still on the stack */2404fixSavedPC(currentThread, decompRecord);2405/* Decompile the method */2406jitDecompileMethod(currentThread, decompRecord);2407dumpStack(currentThread, "after jitDecompileAtCurrentPC");2408currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(executeCurrentBytecodeFromJIT);24092410Trc_Decomp_DecompileAtCurrentPC_Exit(currentThread);2411}24122413/* Resolve frame is already built */2414void2415c_jitDecompileBeforeMethodMonitorEnter(J9VMThread *currentThread)2416{2417Trc_Decomp_DecompileBeforeMethodMonitorEnter_Entry(currentThread);24182419/* Fetch and unstack the decompilation information for this frame */2420J9JITDecompilationInfo *decompRecord = fetchAndUnstackDecompilationInfo(currentThread);2421J9Method * const method = decompRecord->method;2422/* Fix the saved PC since the frame is still on the stack */2423fixSavedPC(currentThread, decompRecord);2424/* Decompile the method */2425jitDecompileMethod(currentThread, decompRecord);2426dumpStack(currentThread, "after jitDecompileBeforeMethodMonitorEnter");2427currentThread->floatTemp1 = (void*)method;2428currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(enterMethodMonitorFromJIT);24292430Trc_Decomp_DecompileBeforeMethodMonitorEnter_Exit(currentThread);2431}24322433/* Resolve frame is already built */2434void2435c_jitDecompileBeforeReportMethodEnter(J9VMThread *currentThread)2436{2437Trc_Decomp_DecompileBeforeReportMethodEnter_Entry(currentThread);24382439/* Fetch and unstack the decompilation information for this frame */2440J9JITDecompilationInfo *decompRecord = fetchAndUnstackDecompilationInfo(currentThread);2441J9Method * const method = decompRecord->method;2442/* Fix the saved PC since the frame is still on the stack */2443fixSavedPC(currentThread, decompRecord);2444/* Decompile the method */2445jitDecompileMethod(currentThread, decompRecord);2446dumpStack(currentThread, "after jitDecompileBeforeReportMethodEnter");2447currentThread->floatTemp1 = (void*)method;2448currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(reportMethodEnterFromJIT);24492450Trc_Decomp_DecompileBeforeReportMethodEnter_Exit(currentThread, method);2451}24522453/* Resolve frame is already built */2454void2455c_jitDecompileAfterMonitorEnter(J9VMThread *currentThread)2456{2457Trc_Decomp_DecompileAfterMonitorEnter_Entry(currentThread, currentThread->pc);24582459/* Fetch and unstack the decompilation information for this frame */2460J9JITDecompilationInfo *decompRecord = fetchAndUnstackDecompilationInfo(currentThread);2461/* Fix the saved PC since the frame is still on the stack */2462fixSavedPC(currentThread, decompRecord);2463/* Decompile the method */2464jitDecompileMethod(currentThread, decompRecord);2465/* See if this was actually the monitor enter for an inlined synchronized method. If the current2466* bytecode is not JBmonitorenter, we are at the start of a method (JBmonitorenter can not appear2467* at bytecode 0 in any verified method).2468*/2469if (JBmonitorenter != *currentThread->pc) {2470dumpStack(currentThread, "after jitDecompileAfterMonitorEnter - inlined sync method");2471currentThread->floatTemp1 = (void*)currentThread->literals;2472currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(reportMethodEnterFromJIT);2473} else {2474/* Advance the PC past the monitorenter and resume execution */2475currentThread->pc += 1;2476dumpStack(currentThread, "after jitDecompileAfterMonitorEnter - JBmonitorenter");2477currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(executeCurrentBytecodeFromJIT);2478}24792480Trc_Decomp_DecompileAfterMonitorEnter_Exit(currentThread, currentThread->pc, currentThread->literals);2481}24822483void2484c_jitDecompileOnReturn(J9VMThread *currentThread)2485{2486Trc_Decomp_DecompileOnReturn_Entry(currentThread, currentThread->pc, currentThread->sp);24872488UDATA const slots = currentThread->tempSlot;2489/* Fetch and unstack the decompilation information for this frame */2490J9JITDecompilationInfo *decompRecord = fetchAndUnstackDecompilationInfo(currentThread);2491/* Simulate a call to a resolve helper to make the stack walkable */2492buildBranchJITResolveFrame(currentThread, decompRecord->pc, 0);2493/* Decompile the method */2494jitDecompileMethod(currentThread, decompRecord);2495/* Copy return value to stack */2496currentThread->sp -= slots;2497memmove(currentThread->sp, ¤tThread->returnValue, slots * sizeof(UDATA));2498/* Advance the PC past the invoke and resume execution */2499currentThread->pc += 3;2500dumpStack(currentThread, "after jitDecompileOnReturn");2501currentThread->tempSlot = (UDATA)J9_BUILDER_SYMBOL(executeCurrentBytecodeFromJIT);25022503Trc_Decomp_DecompileOnReturn_Exit(currentThread, currentThread->pc, currentThread->sp, currentThread->returnValue);2504}25052506void2507c_jitReportExceptionCatch(J9VMThread *currentThread)2508{2509void *jitPC = currentThread->floatTemp4;2510J9JavaVM * const vm = currentThread->javaVM;2511/* Simulate a call to a resolve helper to make the stack walkable */2512buildBranchJITResolveFrame(currentThread, jitPC, J9_STACK_FLAGS_JIT_EXCEPTION_CATCH_RESOLVE);2513/* If there was a decompilation record for the frame which is catching the exception, the PC will be2514* pointing to jitDecompileAtExceptionCatch. In this case, update the decompilation record so that the2515* pcAddress points to the PC save location in the newly-pushed resolve frame.2516*/2517if (J9_BUILDER_SYMBOL(jitDecompileAtExceptionCatch) == jitPC) {2518currentThread->decompilationStack->pcAddress = (U_8**)&(((J9SFJITResolveFrame*)currentThread->sp)->returnAddress);2519}2520/* Report the event */2521if (J9_EVENT_IS_HOOKED(vm->hookInterface, J9HOOK_VM_EXCEPTION_CATCH)) {2522j9object_t exception = ((J9SFJITResolveFrame*)currentThread->sp)->savedJITException;2523ALWAYS_TRIGGER_J9HOOK_VM_EXCEPTION_CATCH(vm->hookInterface, currentThread, exception, NULL);2524if (VM_VMHelpers::immediateAsyncPending(currentThread)) {2525if (J9_CHECK_ASYNC_POP_FRAMES == vm->internalVMFunctions->javaCheckAsyncMessages(currentThread, FALSE)) {2526jitPC = J9_BUILDER_SYMBOL(handlePopFramesFromJIT);2527goto done;2528}2529}2530/* Do not cache the resolve frame pointer as the hook call may modify the SP value */2531jitPC = ((J9SFJITResolveFrame*)currentThread->sp)->returnAddress;2532}2533/* Continue running */2534restoreBranchJITResolveFrame(currentThread);2535done:2536currentThread->tempSlot = (UDATA)jitPC;2537}25382539UDATA2540jitIsMethodBreakpointed(J9VMThread *currentThread, J9Method *method)2541{2542return J9_ARE_ANY_BITS_SET((UDATA)method->constantPool, J9_STARTPC_METHOD_BREAKPOINTED);2543}25442545} /* extern "C" */2546254725482549