diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat index a22d539c15c..b4151315093 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat @@ -564,6 +564,15 @@ J9ThreadMonitorPool.entries = required J9ThreadMonitorPool.next = required J9TranslationBufferSet.romClassBuilder = required J9UTF8.length = required +J9VMContinuation.arg0EA = UDATA* +J9VMContinuation.decompilationStack = J9JITDecompilationInfo* +J9VMContinuation.i2jState = J9I2JState +J9VMContinuation.j2iFrame = UDATA* +J9VMContinuation.jitGPRs = J9JITGPRSpillArea +J9VMContinuation.literals = J9Method* +J9VMContinuation.oldEntryLocalStorage = J9VMEntryLocalStorage* +J9VMContinuation.pc = U8* +J9VMContinuation.sp = UDATA* J9VMEntryLocalStorage.i2jState = required J9VMEntryLocalStorage.jitFPRegisterStorageBase = required J9VMEntryLocalStorage.jitGlobalStorageBase = required diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/RootScanner.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/RootScanner.java index 6f106757c2d..3a7f293c8cd 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/RootScanner.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/RootScanner.java @@ -110,12 +110,14 @@ protected RootScanner() throws CorruptDataException private class RootScannerStackWalkerCallbacks implements IStackWalkerCallbacks { - public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkState walkState) + @Override + public FrameCallbackResult frameWalkFunction(WalkState walkState) { return FrameCallbackResult.KEEP_ITERATING; } - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, PointerPointer objectSlot, VoidPointer stackLocation) + @Override + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackLocation) { try { J9ObjectPointer object = J9ObjectPointer.cast(objectSlot.at(0)); @@ -127,8 +129,8 @@ public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkS } } - public void fieldSlotWalkFunction(J9VMThreadPointer walkThread, - WalkState walkState, ObjectReferencePointer objectSlot, + @Override + public void fieldSlotWalkFunction(WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation) { try { diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/StackRoots.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/StackRoots.java index 9a0304113fd..8284e66934e 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/StackRoots.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/StackRoots.java @@ -51,12 +51,14 @@ public class StackRoots private class StackWalkerCallbacks implements IStackWalkerCallbacks { - public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkState walkState) + @Override + public FrameCallbackResult frameWalkFunction(WalkState walkState) { return FrameCallbackResult.KEEP_ITERATING; } - - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) + + @Override + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) { if (walkState.method.isNull()){ /* adding an object slot iterator causes us to be called for @@ -76,10 +78,9 @@ public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkS throw new UnsupportedOperationException("Corrupt objectSlot detected"); } } - - - public void fieldSlotWalkFunction(J9VMThreadPointer walkThread, - WalkState walkState, ObjectReferencePointer objectSlot, + + @Override + public void fieldSlotWalkFunction(WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation) { if (walkState.method.isNull()){ diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/BaseStackWalkerCallbacks.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/BaseStackWalkerCallbacks.java index 27dc209a4d0..69b1aac23d6 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/BaseStackWalkerCallbacks.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/BaseStackWalkerCallbacks.java @@ -24,7 +24,6 @@ import com.ibm.j9ddr.vm29.pointer.ObjectReferencePointer; import com.ibm.j9ddr.vm29.pointer.PointerPointer; import com.ibm.j9ddr.vm29.pointer.VoidPointer; -import com.ibm.j9ddr.vm29.pointer.generated.J9VMThreadPointer; /** * Base implementation of IStackWalkerCallbacks that does performs no-ops @@ -41,22 +40,22 @@ public class BaseStackWalkerCallbacks implements IStackWalkerCallbacks /* (non-Javadoc) * @see com.ibm.j9ddr.vm.j9.stackwalker.IStackWalkerCallbacks#frameWalkFunction(com.ibm.j9ddr.vm.j9.stackwalker.WalkState) */ - public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, - WalkState walkState) + @Override + public FrameCallbackResult frameWalkFunction(WalkState walkState) { // Deliberately do nothing return FrameCallbackResult.KEEP_ITERATING; } - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, - WalkState walkState, PointerPointer objectSlot, + @Override + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackLocation) { // Deliberately do nothing } - public void fieldSlotWalkFunction(J9VMThreadPointer walkThread, - WalkState walkState, ObjectReferencePointer objectSlot, + @Override + public void fieldSlotWalkFunction(WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation) { // Deliberately do nothing diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/IStackWalkerCallbacks.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/IStackWalkerCallbacks.java index 6d771f2be54..1a593fca0cb 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/IStackWalkerCallbacks.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/IStackWalkerCallbacks.java @@ -24,7 +24,6 @@ import com.ibm.j9ddr.vm29.pointer.ObjectReferencePointer; import com.ibm.j9ddr.vm29.pointer.PointerPointer; import com.ibm.j9ddr.vm29.pointer.VoidPointer; -import com.ibm.j9ddr.vm29.pointer.generated.J9VMThreadPointer; /** * Interface for stack-walker callback routines. @@ -35,14 +34,14 @@ public interface IStackWalkerCallbacks { - public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkState walkState); + public FrameCallbackResult frameWalkFunction(WalkState walkState); - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, PointerPointer objectSlot, VoidPointer stackLocation); + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackLocation); /** * This callback doesn't exist in the native C. * * It's purpose in DDR is passing back field slots in stack-allocated objects (which would be incorrectly handled by a PointerPointer) */ - public void fieldSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation); + public void fieldSlotWalkFunction(WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation); } diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java index 66d2e9ecae1..79b7006841e 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/JITStackWalker.java @@ -62,7 +62,6 @@ import com.ibm.j9ddr.vm29.pointer.generated.J9SFNativeMethodFramePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9SFSpecialFramePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9UTF8Pointer; -import com.ibm.j9ddr.vm29.pointer.generated.J9VMThreadPointer; import com.ibm.j9ddr.vm29.pointer.helper.J9UTF8Helper; import com.ibm.j9ddr.vm29.structure.J9ITable; import com.ibm.j9ddr.vm29.structure.J9JITFrame; @@ -106,9 +105,9 @@ static void jitPrintRegisterMapArray(WalkState walkState, String description) th getImpl().jitPrintRegisterMapArray(walkState,description); } - static J9JITExceptionTablePointer jitGetExceptionTableFromPC(J9VMThreadPointer walkThread, U8Pointer pc) throws CorruptDataException + static J9JITExceptionTablePointer jitGetExceptionTableFromPC(J9JavaVMPointer javaVM, U8Pointer pc) throws CorruptDataException { - return getImpl().jitGetExceptionTableFromPC(walkThread, pc); + return getImpl().jitGetExceptionTableFromPC(javaVM, pc); } private static IJITStackWalker impl; @@ -137,7 +136,7 @@ private static interface IJITStackWalker extends IAlgorithm public void jitPrintRegisterMapArray(WalkState walkState, String description) throws CorruptDataException; - public J9JITExceptionTablePointer jitGetExceptionTableFromPC(J9VMThreadPointer walkThread, U8Pointer pc) throws CorruptDataException; + public J9JITExceptionTablePointer jitGetExceptionTableFromPC(J9JavaVMPointer javaVM, U8Pointer pc) throws CorruptDataException; } /** @@ -214,7 +213,7 @@ public FrameCallbackResult jitWalkStackFrames(WalkState walkState) walkState.outgoingArgCount = walkState.argCount; if (((walkState.flags & J9_STACKWALK_SKIP_INLINES) == 0) && getJitInlinedCallInfo(walkState.jitInfo).notNull()) { - jitGetMapsFromPC(walkState.walkThread.javaVM(), walkState.jitInfo, UDATA.cast(walkState.pc), maps); + jitGetMapsFromPC(walkState.javaVM, walkState.jitInfo, UDATA.cast(walkState.pc), maps); if (maps.inlineMap.notNull()) { VoidPointer inlinedCallSite = getFirstInlinedCallSite(walkState.jitInfo, VoidPointer.cast(maps.inlineMap)); walkState.arg0EA = UDATAPointer.NULL; @@ -238,7 +237,7 @@ public FrameCallbackResult jitWalkStackFrames(WalkState walkState) } } } else if ((walkState.flags & J9_STACKWALK_RECORD_BYTECODE_PC_OFFSET) != 0) { - jitGetMapsFromPC(walkState.walkThread.javaVM(), walkState.jitInfo, UDATA.cast(walkState.pc),maps); + jitGetMapsFromPC(walkState.javaVM, walkState.jitInfo, UDATA.cast(walkState.pc), maps); } SET_A0_CP_METHOD(walkState); @@ -278,7 +277,7 @@ public FrameCallbackResult jitWalkStackFrames(WalkState walkState) /* JIT pair with no mapping indicates a bytecoded frame */ failedPC = walkState.pc; - returnTable = PointerPointer.cast(walkState.walkThread.javaVM().jitConfig().i2jReturnTable()); + returnTable = PointerPointer.cast(walkState.javaVM.jitConfig().i2jReturnTable()); if (returnTable.notNull()) { for (i = 0; i < J9SW_JIT_RETURN_TABLE_SIZE; ++i) { if (failedPC.eq(U8Pointer.cast(returnTable.at(i)))) break; @@ -309,11 +308,11 @@ private J9JITExceptionTablePointer jitGetExceptionTable( { /* this is done with a macro in C */ if (! J9BuildFlags.jit_fullSpeedDebug) { - return jitGetExceptionTableFromPC(walkState.walkThread, walkState.pc); + return jitGetExceptionTableFromPC(walkState.javaVM, walkState.pc); } J9JITDecompilationInfoPointer stack; - J9JITExceptionTablePointer result = jitGetExceptionTableFromPC(walkState.walkThread, walkState.pc); + J9JITExceptionTablePointer result = jitGetExceptionTableFromPC(walkState.javaVM, walkState.pc); walkState.decompilationRecord = J9JITDecompilationInfoPointer.NULL; if (result.notNull()) return result; @@ -333,7 +332,7 @@ private J9JITExceptionTablePointer jitGetExceptionTable( } walkState.decompilationRecord = walkState.decompilationStack; walkState.decompilationStack = walkState.decompilationStack.next(); - return jitGetExceptionTableFromPC(walkState.walkThread,walkState.pc); + return jitGetExceptionTableFromPC(walkState.javaVM, walkState.pc); } stack = walkState.decompilationStack; @@ -348,9 +347,9 @@ private J9JITExceptionTablePointer jitGetExceptionTable( } public J9JITExceptionTablePointer jitGetExceptionTableFromPC( - J9VMThreadPointer walkThread, U8Pointer pc) throws CorruptDataException + J9JavaVMPointer javaVM, U8Pointer pc) throws CorruptDataException { - J9JITConfigPointer jitConfig = walkThread.javaVM().jitConfig(); + J9JITConfigPointer jitConfig = javaVM.jitConfig(); if (jitConfig.isNull()) { return J9JITExceptionTablePointer.NULL; @@ -419,7 +418,7 @@ private void jitWalkResolveMethodFrame(WalkState walkState) throws CorruptDataEx ramMethod = J9MethodPointer.cast(iTableOffset).untag(J9_ITABLE_OFFSET_TAG_BITS); } else if (0 != (iTableOffset & J9_ITABLE_OFFSET_VIRTUAL)) { long vTableOffset = iTableOffset & ~J9_ITABLE_OFFSET_TAG_BITS; - J9JavaVMPointer vm = walkState.walkThread.javaVM(); + J9JavaVMPointer vm = walkState.javaVM; // C code uses Object from the VM constant pool, but that's not easily // accessible to DDR. Any class will do. J9ClassPointer clazz = vm.booleanArrayClass(); @@ -646,7 +645,7 @@ private char jitNextSigChar(String signatureString) throws CorruptDataException private U64Pointer jitFPRParmAddress(WalkState walkState, UDATA fpParmNumber) throws CorruptDataException { - U64Pointer base = U64Pointer.cast(walkState.walkedEntryLocalStorage.jitFPRegisterStorageBase()); + U64Pointer base = U64Pointer.cast(walkState.jitFPRegisterStorageBase); if (J9BuildFlags.arch_s390) { /* 390 uses FPR0/2/4/6 for arguments, so double fpParmNumber to get the right register */ @@ -664,7 +663,7 @@ private U64Pointer jitFPRParmAddress(WalkState walkState, UDATA fpParmNumber) th * save slots for JIT FPRs, so if vector registers are enabled, the save location for a * JIT FPR is (base + (16 * 64) + (128 * FPRNumber)), or (base + (64 * (16 + (2 * FPRNumber)))). */ - if (0 != (walkState.walkThread.javaVM().extendedRuntimeFlags().longValue() & J9_EXTENDED_RUNTIME_USE_VECTOR_REGISTERS)) { + if (0 != (walkState.javaVM.extendedRuntimeFlags().longValue() & J9_EXTENDED_RUNTIME_USE_VECTOR_REGISTERS)) { fpParmNumber = fpParmNumber.add(fpParmNumber).add(16); } } @@ -983,7 +982,7 @@ private FrameCallbackResult walkTransitionFrame(WalkState walkState) throws Corr private void jitAddSpilledRegistersForResolve(WalkState walkState) throws CorruptDataException { try { - UDATAPointer slotCursor = walkState.walkedEntryLocalStorage.jitGlobalStorageBase(); + UDATAPointer slotCursor = walkState.jitGlobalStorageBase; int mapCursor = 0; int i; @@ -1000,7 +999,7 @@ private void jitAddSpilledRegistersForResolve(WalkState walkState) throws Corrup private void jitAddSpilledRegistersForINL(WalkState walkState) throws CorruptDataException { - UDATAPointer slotCursor = walkState.walkedEntryLocalStorage.jitGlobalStorageBase(); + UDATAPointer slotCursor = walkState.jitGlobalStorageBase; int i; for (i = 0; i < J9SW_JIT_CALLEE_PRESERVED_SIZE; ++i) { @@ -1079,7 +1078,7 @@ private void jitWalkFrame(WalkState walkState, boolean walkLocals, VoidPointer s WALK_METHOD_CLASS(walkState); if (stackMap.isNull()) { - stackMap = getStackMapFromJitPC(walkState.walkThread.javaVM(), walkState.jitInfo, UDATA.cast(walkState.pc)); + stackMap = getStackMapFromJitPC(walkState.javaVM, walkState.jitInfo, UDATA.cast(walkState.pc)); if (stackMap.isNull()) { throw new AddressedCorruptDataException(walkState.jitInfo.getAddress(),"Unable to locate JIT stack map"); } @@ -1095,7 +1094,7 @@ private void jitWalkFrame(WalkState walkState, boolean walkLocals, VoidPointer s mapBytesRemaining = new UDATA(getJitNumberOfMapBytes(gcStackAtlas)); jitDescriptionCursor = getJitStackSlots(walkState.jitInfo, stackMap); - stackAllocMapCursor = U8Pointer.cast(getStackAllocMapFromJitPC(walkState.walkThread.javaVM(), walkState.jitInfo, UDATA.cast(walkState.pc), stackMap)); + stackAllocMapCursor = U8Pointer.cast(getStackAllocMapFromJitPC(walkState.javaVM, walkState.jitInfo, UDATA.cast(walkState.pc), stackMap)); stackAllocMapBits = new U8(0); walkState.slotType = (int)J9_STACKWALK_SLOT_TYPE_METHOD_LOCAL; @@ -1217,7 +1216,7 @@ stack frame (once for parms and once for autos). swPrintf(walkState, 4, "\t\t\tF-Slot[{0}] = {1}", slot.getHexAddress(), slot.at(0).getHexAddress()); if (walkState.callBacks != null) { - walkState.callBacks.fieldSlotWalkFunction(walkState.walkThread, walkState, slot, VoidPointer.cast(slot)); + walkState.callBacks.fieldSlotWalkFunction(walkState, slot, VoidPointer.cast(slot)); } } @@ -1278,7 +1277,7 @@ private void jitWalkRegisterMap(WalkState walkState, VoidPointer stackMap, J9JIT swPrintf(walkState, 4, "\t\tJIT-RegisterMap-O-Slot[{0}] = {1} ({2})", targetObject.getHexAddress(), oldObject.getHexAddress(), jitRegisterNames[mapCursor]); - walkState.callBacks.objectSlotWalkFunction(walkState.walkThread, walkState, targetObject, VoidPointer.cast(targetObject)); + walkState.callBacks.objectSlotWalkFunction(walkState, targetObject, VoidPointer.cast(targetObject)); newObject = targetObject.isNull() ? J9ObjectPointer.NULL : J9ObjectPointer.cast(targetObject.at(0)); diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/MethodMetaData.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/MethodMetaData.java index 705f0a54057..7be30f9e00f 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/MethodMetaData.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/MethodMetaData.java @@ -1234,7 +1234,7 @@ that does the stack check failure check (can result in GC). Avoid oldPinningArrayAddress.getHexAddress(), walkState.bp.getHexAddress(), offsetOfFirstInternalPtr); - walkState.callBacks.objectSlotWalkFunction(walkState.walkThread, walkState, currPinningArrayCursor, VoidPointer.cast(currPinningArrayCursor)); + walkState.callBacks.objectSlotWalkFunction(walkState, currPinningArrayCursor, VoidPointer.cast(currPinningArrayCursor)); newPinningArrayAddress = J9ObjectPointer.cast( currPinningArrayCursor.at(0) ); displacement = new IDATA( UDATA.cast(newPinningArrayAddress).sub(UDATA.cast(oldPinningArrayAddress))); walkState.slotIndex++; diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalker.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalker.java index a781ee492eb..3e308c97c88 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalker.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalker.java @@ -29,11 +29,11 @@ import com.ibm.j9ddr.InvalidDataTypeException; import com.ibm.j9ddr.corereaders.osthread.IOSThread; import com.ibm.j9ddr.corereaders.osthread.IRegister; -import com.ibm.j9ddr.vm29.pointer.generated.J9JITDecompilationInfoPointer; import com.ibm.j9ddr.vm29.j9.AlgorithmPicker; import com.ibm.j9ddr.vm29.j9.AlgorithmVersion; import com.ibm.j9ddr.vm29.j9.BaseAlgorithm; import com.ibm.j9ddr.vm29.j9.ConstantPoolHelpers; +import com.ibm.j9ddr.vm29.j9.DataType; import com.ibm.j9ddr.vm29.j9.IAlgorithm; import com.ibm.j9ddr.vm29.pointer.PointerPointer; import com.ibm.j9ddr.vm29.pointer.U32Pointer; @@ -42,7 +42,7 @@ import com.ibm.j9ddr.vm29.pointer.VoidPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9BuildFlags; import com.ibm.j9ddr.vm29.pointer.generated.J9ConstantPoolPointer; -import com.ibm.j9ddr.vm29.pointer.generated.J9I2JStatePointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9JITDecompilationInfoPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9JITExceptionTablePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9MethodPointer; @@ -55,7 +55,10 @@ import com.ibm.j9ddr.vm29.pointer.generated.J9SFMethodTypeFramePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9SFSpecialFramePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9SFStackFramePointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9VMContinuationPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9VMEntryLocalStoragePointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9VMThreadPointer; +import com.ibm.j9ddr.vm29.pointer.helper.J9RASHelper; import com.ibm.j9ddr.vm29.pointer.helper.J9ROMMethodHelper; import com.ibm.j9ddr.vm29.pointer.helper.J9ThreadHelper; import com.ibm.j9ddr.vm29.pointer.helper.J9UTF8Helper; @@ -81,9 +84,9 @@ /** * StackWalker - * + * * @author andhall - * + * */ public class StackWalker { @@ -95,14 +98,15 @@ public static StackWalkResult walkStackFrames(WalkState walkState) { return getImpl().walkStackFrames(walkState); } - + /** - * use user provided sp, arg0ea, pc, literal and entryLocalStorage + * use continuation's sp, arg0ea, pc, literal and entryLocalStorage. */ - public static StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDATAPointer arg0ea, U8Pointer pc, J9MethodPointer literals, J9VMEntryLocalStoragePointer entryLocalStorage) { - return getImpl().walkStackFrames(walkState, sp, arg0ea, pc, literals, entryLocalStorage); + public static StackWalkResult walkStackFrames(WalkState walkState, long continuationAddress) + { + return getImpl().walkStackFrames(walkState, continuationAddress); } - + /* Callback from JIT stack walker */ static FrameCallbackResult walkFrame(WalkState walkState) throws CorruptDataException { @@ -117,7 +121,7 @@ public static void walkBytecodeFrameSlots(WalkState walkState, J9MethodPointer m } private static IStackWalker impl; - + private static final AlgorithmPicker picker = new AlgorithmPicker(AlgorithmVersion.STACK_WALKER_VERSION){ @Override @@ -127,7 +131,7 @@ protected Iterable allAlgorithms() toReturn.add(new StackWalker_29_V0()); return toReturn; }}; - + private static IStackWalker getImpl() { if (impl == null) { @@ -139,116 +143,146 @@ private static IStackWalker getImpl() private static interface IStackWalker extends IAlgorithm { public StackWalkResult walkStackFrames(WalkState walkState); - + + public StackWalkResult walkStackFrames(WalkState walkState, long continuationAddress); + public void walkBytecodeFrameSlots(WalkState walkState, J9MethodPointer method, UDATA offsetPC, UDATAPointer pendingBase, UDATA pendingStackHeight, UDATAPointer localBase, UDATA numberOfLocals) throws CorruptDataException; - public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDATAPointer arg0ea, U8Pointer pc, J9MethodPointer literals, J9VMEntryLocalStoragePointer entryLocalStorage); - FrameCallbackResult walkFrame(WalkState walkState) throws CorruptDataException; } - - + + private static class StackWalker_29_V0 extends BaseAlgorithm implements IStackWalker { - + protected StackWalker_29_V0() { super(90, 0); } - public StackWalkResult walkStackFrames(WalkState walkState) - { + @Override + public StackWalkResult walkStackFrames(WalkState walkState) { + J9VMThreadPointer walkThread = walkState.walkThread; try { - return walkStackFrames(walkState, - walkState.walkThread.sp(), - walkState.walkThread.arg0EA(), - walkState.walkThread.pc(), - walkState.walkThread.literals(), - walkState.walkThread.entryLocalStorage()); + walkState.javaVM = walkThread.javaVM(); + walkState.threadAddress = walkThread.getAddress(); + walkState.osThread = J9ThreadHelper.getOSThread(walkThread.osThread()); + walkState.privateFlags = walkThread.privateFlags(); + if (walkState.arg0EA == null) { + walkState.arg0EA = walkThread.arg0EA(); + } + if (walkState.pc == null) { + walkState.pc = walkThread.pc(); + } + walkState.pcAddress = walkThread.pcEA(); + if (walkState.walkSP == null) { + walkState.walkSP = walkThread.sp(); + } + if (walkState.literals == null) { + walkState.literals = walkThread.literals(); + } + J9VMEntryLocalStoragePointer els = walkThread.entryLocalStorage(); + if (walkState.oldEntryLocalStorage == null) { + walkState.fillElsFields(els); + } + walkState.j2iFrame = walkThread.j2iFrame(); + walkState.decompilationStack = walkThread.decompilationStack(); } catch (CorruptDataException ex) { - raiseCorruptDataEvent("CDE thrown extracting initial stack walk state. walkThread = " + walkState.walkThread.getHexAddress(), ex, true); + raiseCorruptDataEvent("CDE thrown extracting initial stack walk state. walkThread = " + walkThread.getHexAddress(), ex, true); return StackWalkResult.STACK_CORRUPT; } + return commonWalker(walkState); } - - public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDATAPointer arg0ea, U8Pointer pc, J9MethodPointer literals, J9VMEntryLocalStoragePointer entryLocalStorage) + + @Override + public StackWalkResult walkStackFrames(WalkState walkState, long continuationAddress) { + try { + J9VMContinuationPointer continuation = J9VMContinuationPointer.cast(continuationAddress); + + walkState.javaVM = J9RASHelper.getVM(DataType.getJ9RASPointer()); + walkState.threadAddress = continuation.getAddress(); + walkState.arg0EA = continuation.arg0EA(); + walkState.pc = continuation.pc(); + walkState.pcAddress = continuation.pcEA(); + walkState.walkSP = continuation.sp(); + walkState.literals = continuation.literals(); + walkState.privateFlags = new UDATA(0); + walkState.j2iFrame = continuation.j2iFrame(); + walkState.decompilationStack = continuation.decompilationStack(); + + walkState.i2jState = continuation.i2jState(); + walkState.jitGlobalStorageBase = UDATAPointer.cast(continuation.jitGPRs()); + walkState.jitFPRegisterStorageBase = UDATAPointer.NULL; + walkState.oldEntryLocalStorage = continuation.oldEntryLocalStorage(); + } catch (NoClassDefFoundError | NoSuchFieldException e) { + /* The exception will be thrown if the related classes or fields cannot be found in the core file. + * This could be caused by either that the Java version of the core file is below 19 or that the + * core file is corrupted. Since the version has been checked in the continuation stackwalk command, + * we can conclude that the core file is corrupted. + */ + return StackWalkResult.STACK_CORRUPT; + } catch (CorruptDataException ex) { + raiseCorruptDataEvent("CDE thrown extracting initial stack walk state. walkThread = " + String.format("0x%0" + (UDATA.SIZEOF * 2) + "X", continuationAddress), ex, true); + return StackWalkResult.STACK_CORRUPT; + } + return commonWalker(walkState); + } + + private StackWalkResult commonWalker(WalkState walkState) { UDATAPointer nextA0 = null; U8Pointer nextPC = null; J9MethodPointer nextLiterals; - - StackWalkResult rc = null; - try { - rc = walkState.walkThread.privateFlags().anyBitsIn(J9_PRIVATE_FLAGS_STACK_CORRUPT) ? StackWalkResult.STACK_CORRUPT : StackWalkResult.NONE; - } catch (CorruptDataException e) { - raiseCorruptDataEvent("CDE thrown extracting walkThread privateFlags. walkThread = " + walkState.walkThread.getHexAddress(), e, true); - return StackWalkResult.STACK_CORRUPT; - } - + + StackWalkResult rc = walkState.privateFlags.anyBitsIn(J9_PRIVATE_FLAGS_STACK_CORRUPT) + ? StackWalkResult.STACK_CORRUPT + : StackWalkResult.NONE; + /* Java-implementation specific variables start */ boolean endOfStackReached = false; boolean keepWalking = true; boolean startAtJITFrame = false; - + resetOSlotsCorruptionThreshold(); - + /* End of Java-implementation-specific variables */ - + if ((walkState.flags & J9_STACKWALK_SAVE_STACKED_REGISTERS) != 0) { throw new UnsupportedOperationException("J9_STACKWALK_SAVE_STACKED_REGISTERS not supported by offline walker"); } - - try { - walkState.framesWalked = 0; - walkState.previousFrameFlags = new UDATA(0); - walkState.searchFrameFound = false; - walkState.arg0EA = arg0ea; - walkState.pc = pc; - walkState.pcAddress = walkState.walkThread.pcEA(); - walkState.walkSP = sp; - walkState.literals = literals; - walkState.argCount = new UDATA(0); - walkState.frameFlags = new UDATA(0); - - if (J9BuildFlags.interp_nativeSupport) { - walkState.jitInfo = J9JITExceptionTablePointer.NULL; - walkState.inlineDepth = 0; - walkState.inlinerMap = null; - walkState.walkedEntryLocalStorage = entryLocalStorage; - //TODO this is &i2jState in the C code. Find out why it's different - walkState.i2jState = walkState.walkedEntryLocalStorage.notNull() ? walkState.walkedEntryLocalStorage - .i2jState() - : null; - walkState.j2iFrame = walkState.walkThread.j2iFrame(); - - if (J9BuildFlags.jit_fullSpeedDebug) { - walkState.decompilationStack = walkState.walkThread - .decompilationStack(); - walkState.decompilationRecord = J9JITDecompilationInfoPointer.NULL; - walkState.resolveFrameFlags = new UDATA(0); - } + + walkState.framesWalked = 0; + walkState.previousFrameFlags = new UDATA(0); + walkState.searchFrameFound = false; + walkState.argCount = new UDATA(0); + walkState.frameFlags = new UDATA(0); + + if (J9BuildFlags.interp_nativeSupport) { + walkState.jitInfo = J9JITExceptionTablePointer.NULL; + walkState.inlineDepth = 0; + walkState.inlinerMap = null; + + if (J9BuildFlags.jit_fullSpeedDebug) { + walkState.decompilationRecord = J9JITDecompilationInfoPointer.NULL; + walkState.resolveFrameFlags = new UDATA(0); } - - } catch (CorruptDataException ex) { - raiseCorruptDataEvent("CDE thrown extracting initial stack walk state. walkThread = " + walkState.walkThread.getHexAddress(), ex, true); - return StackWalkResult.STACK_CORRUPT; } /* fix up walkState values if we're starting in an inflight frame */ try { - IOSThread nativeThread = J9ThreadHelper.getOSThread(walkState.walkThread.osThread()); - + IOSThread nativeThread = walkState.osThread; + if (nativeThread != null) { /* TODO: the jit map code subtracts 1 from this value because it expects the trap handlers to have added one * to move the instruction to the target of the return from a child procedure. Do we need to alter it here on z/OS? */ /* does the current eip correspond to a jit exception table? */ long eip = nativeThread.getInstructionPointer(); - - J9JITExceptionTablePointer table = jitGetExceptionTableFromPC(walkState.walkThread, U8Pointer.cast(eip)); + + J9JITExceptionTablePointer table = jitGetExceptionTableFromPC(walkState.javaVM, U8Pointer.cast(eip)); if (!table.isNull()) { /* there's an exception table associated with this address so we're in jitted code. Let's try fixing it up */ @@ -307,7 +341,7 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA swPrintf(walkState, 1, "*** BEGIN STACK WALK, flags = {0} walkThread = {1} ***", - String.format("%08X", walkState.flags), walkState.walkThread.getHexAddress()); + String.format("%08X", walkState.flags), walkState.threadAddress); if ((walkState.flags & J9_STACKWALK_START_AT_JIT_FRAME) != 0) swPrintf(walkState, 2, "\tSTART_AT_JIT_FRAME"); @@ -335,7 +369,7 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA swPrintf(walkState, 2, "\tHIDE_EXCEPTION_FRAMES"); if ((walkState.flags & J9_STACKWALK_RECORD_BYTECODE_PC_OFFSET) != 0) swPrintf(walkState, 2, "\tRECORD_BYTECODE_PC_OFFSET"); - + //TODO why is the throwing exception stuff left out? swPrintf( walkState, @@ -350,13 +384,11 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA + walkState.arg0EA.getHexAddress() + ", j2iFrame = " + (J9BuildFlags.interp_nativeSupport ? walkState.j2iFrame.getHexAddress() : "0") - + ", ELS = " - + (J9BuildFlags.interp_nativeSupport ? walkState.walkedEntryLocalStorage.getHexAddress() : "0") + ", decomp = " + (J9BuildFlags.jit_fullSpeedDebug ? walkState.decompilationStack.getHexAddress() : "0") ); - + if (((walkState.flags & J9_STACKWALK_COUNT_SPECIFIED) != 0) && (walkState.maxFrames == 0)) { keepWalking = false; @@ -364,35 +396,35 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA } //TODO missing initializeObjectSlotBitVector - + if (J9BuildFlags.interp_nativeSupport) { if (walkState.flags == J9_STACKWALK_ITERATE_O_SLOTS) { walkState.flags |= J9_STACKWALK_SKIP_INLINES; } - + if ((walkState.flags & J9_STACKWALK_ITERATE_O_SLOTS) != 0) { walkState.flags |= J9_STACKWALK_MAINTAIN_REGISTER_MAP; } - + if ((walkState.flags & J9_STACKWALK_START_AT_JIT_FRAME) != 0) { // goto jitFrame startAtJITFrame = true; } } - + // Check callbacks have been provided if required if ((walkState.flags & (J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_ITERATE_O_SLOTS)) != 0 && walkState.callBacks == null) { throw new NullPointerException( "User requested iterate frames or slots and didn't provide a callback. See WalkState.callBacks."); } - + try { WALKING_LOOP: while (keepWalking) { J9SFStackFramePointer fixedStackFrame; - + swPrintf(walkState, 200, "Top of WALKING_LOOP"); - + if (!startAtJITFrame) { walkState.constantPool = J9ConstantPoolPointer.NULL; walkState.unwindSP = UDATAPointer.NULL; @@ -400,7 +432,7 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA walkState.sp = walkState.walkSP.sub(walkState.argCount); walkState.outgoingArgCount = walkState.argCount; walkState.bytecodePCOffset = U8Pointer.cast(-1); - + if (walkState.pc.getAddress() == J9SF_FRAME_TYPE_END_OF_STACK) { // goto endOfStack; swPrintf(walkState, 200, "PC Switch: End of Stack"); @@ -434,11 +466,10 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA "Aborting walk due to unknown special frame type"); break WALKING_LOOP; } - - if ((walkState.pc.eq(walkState.walkThread.javaVM() - .callInReturnPC())) + + if ((walkState.pc.eq(walkState.javaVM.callInReturnPC())) || (walkState.pc - .eq(walkState.walkThread.javaVM() + .eq(walkState.javaVM .callInReturnPC().addOffset(3)))) { swPrintf(walkState, 200, "PC Switch: default: walkJNICallInFrame"); @@ -449,13 +480,13 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA walkBytecodeFrame(walkState); } } - + /* * Fetch the PC value before calling the frame walker since * the debugger modifies PC values when breakpointing * methods */ - + { UDATA nextPCUDATA = new UDATA(walkState.bp.getAddress()); nextPCUDATA = nextPCUDATA.sub(J9SFStackFrame.SIZEOF); @@ -464,17 +495,17 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA .cast(nextPCUDATA); nextPC = tmpFrame.savedPC(); } - + /* Walk the frame */ - + if (walkFrame(walkState) != FrameCallbackResult.KEEP_ITERATING) { break WALKING_LOOP; } walkState.previousFrameFlags = walkState.frameFlags; walkState.resolveFrameFlags = new UDATA(0); - + } // End of (! startAtJITFrame) - + /* * Call the JIT walker if the current frame is a transition from * the JIT to the interpreter @@ -490,18 +521,18 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA continue WALKING_LOOP; } } - + /* * Fetch the remaining frame values after calling the frame * walker since the stack could grow during the iterator, * changing all stack pointer values */ fixedStackFrame = J9SFStackFramePointer.cast(walkState.bp.subOffset(J9SFStackFrame.SIZEOF).addOffset(UDATA.SIZEOF)); - + nextLiterals = fixedStackFrame.savedCP(); // See definition for UNTAG2 and UNTAGGED_A0 nextA0 = UDATAPointer.cast(fixedStackFrame.savedA0()).untag(); - + /* Move to next frame */ walkState.pcAddress = fixedStackFrame.savedPCEA(); walkState.walkSP = walkState.arg0EA.add(1); @@ -510,39 +541,39 @@ public StackWalkResult walkStackFrames(WalkState walkState, UDATAPointer sp, UDA walkState.arg0EA = nextA0; } } catch (CorruptDataException ex) { - raiseCorruptDataEvent("CorruptDataException thrown walking stack. walkThread = "+ walkState.walkThread.getHexAddress(), ex, false); + raiseCorruptDataEvent("CorruptDataException thrown walking stack. walkThread = "+ walkState.getThreadHexAddress(), ex, false); return StackWalkResult.STACK_CORRUPT; } - + // endOfStack: if (endOfStackReached) { swPrintf(walkState, 2, ""); } - + //If we disabled o-slots walking because it kept throwing CorruptDataException, reset the rc here if (oSlotsCorruptionThresholdReached() && rc == StackWalkResult.NONE) { rc = StackWalkResult.STACK_CORRUPT; } - + // terminationPoint: - + swPrintf(walkState, 1, "*** END STACK WALK (rc = {0}) ***", rc); - + return rc; } - + private void walkMethodFrame(WalkState walkState) throws CorruptDataException { J9SFMethodFramePointer methodFrame = J9SFMethodFramePointer .cast(walkState.walkSP .addOffset(UDATA.cast(walkState.literals))); - + walkState.bp = UDATAPointer.cast(methodFrame.savedA0EA()); walkState.frameFlags = methodFrame.specialFrameFlags(); walkState.method = methodFrame.method(); walkState.unwindSP = UDATAPointer.cast(methodFrame); - + try { if (walkState.pc.getAddress() == J9SF_FRAME_TYPE_METHOD) { printFrameType( @@ -569,7 +600,7 @@ private void walkMethodFrame(WalkState walkState) .anyBitsIn(J9_STACK_FLAGS_JIT_NATIVE_TRANSITION) ? "JIT unknown transition" : "Unknown method"); } - + if (((walkState.flags & J9_STACKWALK_ITERATE_O_SLOTS) != 0) && walkState.literals.notNull()) { if (walkState.frameFlags.anyBitsIn(J9_SSF_JNI_REFS_REDIRECTED)) { @@ -581,24 +612,24 @@ private void walkMethodFrame(WalkState walkState) } catch (CorruptDataException ex) { handleOSlotsCorruption(walkState, "StackWalker_29_V0", "walkMethodFrame", ex); } - + if (walkState.method.notNull()) { J9ROMMethodPointer romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState.method); - + walkState.constantPool = ConstantPoolHelpers.J9_CP_FROM_METHOD(walkState.method); walkState.argCount = new UDATA(romMethod.argCount()); - + if ((walkState.flags & J9_STACKWALK_ITERATE_O_SLOTS) != 0) { try { WALK_METHOD_CLASS(walkState); - + if (walkState.argCount.longValue() != 0) { /* Max size as argCount always <= 255 */ int[] result = new int[8]; - + swPrintf(walkState, 4, "\tUsing signature mapper"); j9localmap_ArgBitsForPC0(romMethod, result); - + swPrintf(walkState, 4, "\tArguments starting at {0} for {1} slots", walkState.arg0EA.getHexAddress(), @@ -635,9 +666,9 @@ private void walkMethodFrame(WalkState walkState) walkState.constantPool = null; walkState.argCount = new UDATA(0); } - + } - + private void walkMethodTypeFrame(WalkState walkState) throws CorruptDataException { @@ -663,25 +694,25 @@ private void walkMethodTypeFrame(WalkState walkState) walkState.slotIndex = 0; walkDescribedPushes(walkState, walkState.arg0EA, walkState.argCount.intValue(), descriptionSlots, walkState.argCount.intValue()); } - + } - + private void walkJNIRefs(WalkState walkState, UDATAPointer currentRef, int refCount) throws CorruptDataException { swPrintf(walkState, 4, "\tJNI local ref pushes starting at {0} for {1} slots", currentRef.getHexAddress(), refCount); - + walkState.slotType = (int)J9_STACKWALK_SLOT_TYPE_JNI_LOCAL; walkState.slotIndex = 0; - + do { if (currentRef.at(0).anyBitsIn(1)) { // J9Object **realRef = (J9Object **) (*currentRef & ~1); PointerPointer realRef = PointerPointer.cast(currentRef.at(0) .bitAnd(new UDATA(1).bitNot())); - + /* * There's no need to mark indirect slots as object since they * will never point to valid objects (so will not be whacked) @@ -694,7 +725,7 @@ private void walkJNIRefs(WalkState walkState, UDATAPointer currentRef, walkState.slotIndex++; } while (--refCount > 0); } - + private void walkIndirectDescribedPushes(WalkState walkState, UDATAPointer highestIndirectSlot, int slotCount, int[] descriptionSlots) throws CorruptDataException @@ -702,7 +733,7 @@ private void walkIndirectDescribedPushes(WalkState walkState, int descriptionBitsRemaining = 0; int description = 0; int descriptionSlotPointer = 0; - + while (slotCount > 0) { if (descriptionBitsRemaining == 0) { description = descriptionSlots[descriptionSlotPointer++]; @@ -730,7 +761,7 @@ private void walkIndirectDescribedPushes(WalkState walkState, .cast(highestIndirectSlot)); } } - + description >>= 1; --descriptionBitsRemaining; highestIndirectSlot = highestIndirectSlot.sub(1); @@ -738,29 +769,29 @@ private void walkIndirectDescribedPushes(WalkState walkState, ++(walkState.slotIndex); } } - + private void walkObjectPushes(WalkState walkState) throws CorruptDataException { UDATA byteCount = UDATA.cast(walkState.literals); PointerPointer currentSlot = PointerPointer.cast(walkState.walkSP); - + swPrintf(walkState, 4, "\tObject pushes starting at {0} for {1} slots", currentSlot.getHexAddress(), byteCount.longValue() / UDATA.SIZEOF); - + walkState.slotType = (int)J9_STACKWALK_SLOT_TYPE_INTERNAL; walkState.slotIndex = 0; - + while (!byteCount.eq(0)) { WALK_NAMED_O_SLOT(walkState, currentSlot, "Push"); currentSlot = currentSlot.add(1); byteCount = byteCount.sub(UDATA.SIZEOF); ++(walkState.slotIndex); } - + } - + private void walkPushedJNIRefs(WalkState walkState) throws CorruptDataException { @@ -769,50 +800,50 @@ private void walkPushedJNIRefs(WalkState walkState) // TODO think about unsigned 64 bit divide UDATA pushCount = new UDATA(walkState.literals.getAddress() / UDATA.SIZEOF).sub(refCount); - + if (!pushCount.eq(0)) { walkState.literals = J9MethodPointer.cast(pushCount.longValue() * UDATA.SIZEOF); walkObjectPushes(walkState); } - + if (!refCount.eq(0)) { walkJNIRefs(walkState, walkState.walkSP.add(pushCount), refCount .intValue()); } } - + public FrameCallbackResult walkFrame(WalkState walkState) throws CorruptDataException { if ((walkState.flags & J9_STACKWALK_VISIBLE_ONLY) != 0) { - if ((UDATA.cast(walkState.pc).eq(J9SF_FRAME_TYPE_NATIVE_METHOD) || + if ((UDATA.cast(walkState.pc).eq(J9SF_FRAME_TYPE_NATIVE_METHOD) || UDATA.cast(walkState.pc).eq(J9SF_FRAME_TYPE_JNI_NATIVE_METHOD)) && ((walkState.flags & J9_STACKWALK_INCLUDE_NATIVES) == 0)) { return FrameCallbackResult.KEEP_ITERATING; } - + if ((!J9BuildFlags.interp_nativeSupport) || walkState.jitInfo.isNull()) { - + if (walkState.bp.at(0).anyBitsIn(J9SF_A0_INVISIBLE_TAG)) { if ((walkState.flags & J9_STACKWALK_INCLUDE_CALL_IN_FRAMES) == 0 - || !walkState.pc.eq(walkState.walkThread.javaVM() + || !walkState.pc.eq(walkState.javaVM .callInReturnPC())) { return FrameCallbackResult.KEEP_ITERATING; } } - + } - + if (walkState.skipCount > 0) { --walkState.skipCount; return FrameCallbackResult.KEEP_ITERATING; } - + if ((walkState.flags & J9_STACKWALK_HIDE_EXCEPTION_FRAMES) != 0) { J9ROMMethodPointer romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState.method); - + if (!romMethod.modifiers().anyBitsIn(J9AccStatic)) { if (J9UTF8Helper.stringValue(romMethod.nameAndSignature().name()) .charAt(0) == '<') { @@ -825,9 +856,9 @@ public FrameCallbackResult walkFrame(WalkState walkState) } } } - + // Caching code not reproduced in offline walker - + ++walkState.framesWalked; // Named block to imitate goto behaviour walkIt: do { @@ -836,28 +867,27 @@ public FrameCallbackResult walkFrame(WalkState walkState) break walkIt; } } - + if ((walkState.flags & J9_STACKWALK_ITERATE_FRAMES) != 0) { break walkIt; } - + return FrameCallbackResult.KEEP_ITERATING; } while (false); - + // walkIt: if ((walkState.flags & J9_STACKWALK_ITERATE_FRAMES) != 0) { - FrameCallbackResult rc = walkState.callBacks.frameWalkFunction( - walkState.walkThread, walkState); - + FrameCallbackResult rc = walkState.callBacks.frameWalkFunction(walkState); + if ((walkState.flags & J9_STACKWALK_COUNT_SPECIFIED) != 0) { if (walkState.framesWalked == walkState.maxFrames) { rc = FrameCallbackResult.STOP_ITERATING; } } - + return rc; } - + return FrameCallbackResult.STOP_ITERATING; } @@ -875,7 +905,7 @@ public void walkBytecodeFrameSlots(WalkState walkState, J9MethodPointer method, * / result logic here. */ int[] result; - + swPrintf(walkState, 3, "\tBytecode index = {0}", offsetPC.longValue()); if (romMethod.modifiers().anyBitsIn(J9AccSynchronized)) { @@ -892,10 +922,10 @@ public void walkBytecodeFrameSlots(WalkState walkState, J9MethodPointer method, WALK_NAMED_O_SLOT(walkState, PointerPointer.cast(bp.add(1)), "Receiver O-Slot"); numberOfMappedLocals = numberOfMappedLocals.sub(1); } - + swPrintf(walkState, 200, "numberOfMappedLocals={0}, pendingStackHeight={1}", numberOfMappedLocals.getHexValue(), pendingStackHeight.getHexValue()); - + int resultArraySize = 0; if (numberOfMappedLocals.gt(32) || pendingStackHeight.gt(32)) { UDATA maxCount = numberOfMappedLocals.gt(pendingStackHeight) ? numberOfMappedLocals @@ -910,7 +940,7 @@ public void walkBytecodeFrameSlots(WalkState walkState, J9MethodPointer method, } swPrintf(walkState, 200, "Result array size = {0}", resultArraySize); result = new int[resultArraySize]; - + if (numberOfMappedLocals.intValue() != 0) { getLocalsMap(walkState, romClass, romMethod, U8Pointer.cast(offsetPC), result, numberOfMappedLocals); swPrintf(walkState, 4, "\tLocals starting at {0} for {1} slots", @@ -919,7 +949,7 @@ public void walkBytecodeFrameSlots(WalkState walkState, J9MethodPointer method, walkState.slotIndex = 0; walkDescribedPushes(walkState, localBase, numberOfMappedLocals.intValue(), result, romMethod.argCount().intValue()); } - + if (pendingStackHeight.intValue() != 0) { getStackMap(walkState, romClass, romMethod, offsetPC, pendingStackHeight, result); swPrintf(walkState, 4, @@ -952,13 +982,13 @@ private void walkBytecodeFrame(WalkState walkState) walkState.unwindSP = UDATAPointer.NULL; walkState.frameFlags = new UDATA(0); // TODO can we avoid crashing? - printFrameType(walkState, "BAD bytecode (expect crash)"); + printFrameType(walkState, "BAD bytecode (expect crash)"); } } else { UDATA argTempCount; J9ROMMethodPointer romMethod; - J9JavaVMPointer vm = walkState.walkThread.javaVM(); - + J9JavaVMPointer vm = walkState.javaVM; + walkState.constantPool = ConstantPoolHelpers.J9_CP_FROM_METHOD(walkState.method); boolean isImpdep1 = false; try { @@ -967,18 +997,18 @@ private void walkBytecodeFrame(WalkState walkState) // impdep1PC field is disabled for OJDK method handles } if (!isImpdep1) { - walkState.bytecodePCOffset = walkState.pc.sub(walkState.method.bytecodes().getAddress()); + walkState.bytecodePCOffset = walkState.pc.sub(walkState.method.bytecodes().getAddress()); } else { walkState.bytecodePCOffset = U8Pointer.NULL; } romMethod = getOriginalROMMethod(walkState.method); - + walkState.argCount = new UDATA(J9_ARG_COUNT_FROM_ROM_METHOD(romMethod)); argTempCount = new UDATA(J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod)) .add(walkState.argCount); walkState.bp = UDATAPointer.cast(walkState.arg0EA).sub(argTempCount); - + if (romMethod.modifiers().anyBitsIn(J9AccSynchronized)) { argTempCount = argTempCount.add(1); walkState.bp = walkState.bp.sub(1); @@ -986,7 +1016,7 @@ private void walkBytecodeFrame(WalkState walkState) argTempCount = argTempCount.add(1); walkState.bp = walkState.bp.sub(1); } - + if (J9BuildFlags.interp_nativeSupport && walkState.bp.eq(walkState.j2iFrame)) { walkState.unwindSP = walkState.bp.subOffset(J9SFJ2IFrame.SIZEOF) @@ -999,7 +1029,7 @@ private void walkBytecodeFrame(WalkState walkState) .addOffset(UDATA.SIZEOF); walkState.frameFlags = new UDATA(0); } - + try { printFrameType(walkState, walkState.frameFlags.intValue() != 0 ? "J2I" : "Bytecode"); @@ -1012,16 +1042,16 @@ private void walkBytecodeFrame(WalkState walkState) } } catch (CorruptDataException ex) { handleOSlotsCorruption(walkState, "StackWalker_29_V0", "walkBytecodeFrame", ex); - } + } } } - + private void getStackMap(WalkState walkState, J9ROMClassPointer romClass, J9ROMMethodPointer romMethod, UDATA offsetPC, UDATA pushCount, int[] result) throws CorruptDataException { int errorCode; - + errorCode = j9stackmap_StackBitsForPC(offsetPC, romClass, romMethod, result, pushCount.intValue()); if (errorCode < 0) { @@ -1030,7 +1060,7 @@ private void getStackMap(WalkState walkState, J9ROMClassPointer romClass, } return; } - + private void walkDescribedPushes(WalkState walkState, UDATAPointer highestSlot, int slotCount, int[] descriptionSlots, int argCount) throws CorruptDataException @@ -1038,7 +1068,7 @@ private void walkDescribedPushes(WalkState walkState, int descriptionBitsRemaining = 0; int description = 0; int descriptionSlotPointer = 0; - + while (slotCount > 0) { if (descriptionBitsRemaining == 0) { description = descriptionSlots[descriptionSlotPointer++]; @@ -1051,14 +1081,14 @@ private void walkDescribedPushes(WalkState walkState, } else { indexedTag = String.format("%s-Slot: p%d", ((description & 1) != 0) ? "O" : "I" ,walkState.slotIndex); } - + if ((description & 1) != 0) { WALK_NAMED_O_SLOT(walkState, PointerPointer.cast(highestSlot), indexedTag); } else { WALK_NAMED_I_SLOT(walkState, PointerPointer.cast(highestSlot), indexedTag); } } - + description >>= 1; --descriptionBitsRemaining; highestSlot = highestSlot.sub(1); @@ -1066,14 +1096,14 @@ private void walkDescribedPushes(WalkState walkState, ++(walkState.slotIndex); } } - + private static void getLocalsMap(WalkState walkState, J9ROMClassPointer romClass, J9ROMMethodPointer romMethod, U8Pointer offsetPC, int[] result, UDATA argTempCount) throws CorruptDataException { int errorCode; - + /* * Detect method entry vs simply executing at PC 0. If the bytecode * frame is invisible (method monitor enter or stack growth) or the @@ -1083,7 +1113,7 @@ private static void getLocalsMap(WalkState walkState, * enter events, even if the receiver is never used (in which case the * local mapper would mark it as int). */ - + if ((walkState.bp.at(0).anyBitsIn(J9SF_A0_INVISIBLE_TAG)) || (walkState.previousFrameFlags.anyBitsIn(J9_SSF_METHOD_ENTRY))) { if ((walkState.bp.at(0).anyBitsIn(J9SF_A0_INVISIBLE_TAG))) { @@ -1097,7 +1127,7 @@ private static void getLocalsMap(WalkState walkState, 4, "\tAt method entry (previous frame = report monitor enter), using signature mapper"); } - + /* * j9localmap_ArgBitsForPC0 only deals with args, so zero out the * result array to make sure the temps are non-object @@ -1111,7 +1141,7 @@ private static void getLocalsMap(WalkState walkState, canAccessLocalsBit = J9JavaVM.J9VM_DEBUG_ATTRIBUTE_CAN_ACCESS_LOCALS; } - if (walkState.walkThread.javaVM().requiredDebugAttributes().anyBitsIn(canAccessLocalsBit)) { + if (walkState.javaVM.requiredDebugAttributes().anyBitsIn(canAccessLocalsBit)) { swPrintf(walkState, 4, "\tUsing debug local mapper"); errorCode = j9localmap_DebugLocalBitsForPC(romMethod, UDATA .cast(offsetPC), result); @@ -1120,35 +1150,35 @@ private static void getLocalsMap(WalkState walkState, errorCode = j9localmap_LocalBitsForPC(romMethod, UDATA .cast(offsetPC), result); } - + if (errorCode < 0) { swPrintf(walkState, 3, "Local map failed, result = {0}", errorCode); /* * Local map failed, result = %p - aborting VM - needs new message * TBD */ - throw new CorruptDataException("Local map failed thread " + walkState.walkThread.getHexAddress() + ", romMethod = " + romMethod.getHexAddress() + ", result - " + errorCode); + throw new CorruptDataException("Local map failed thread " + walkState.getThreadHexAddress() + ", romMethod = " + romMethod.getHexAddress() + ", result - " + errorCode); } - + return; } - + private void walkJNICallInFrame(WalkState walkState) throws CorruptDataException { J9SFJNICallInFramePointer callInFrame; - + walkState.bp = walkState.arg0EA; callInFrame = J9SFJNICallInFramePointer.cast(walkState.bp.subOffset( J9SFJNICallInFrame.SIZEOF).addOffset(UDATA.SIZEOF)); - + /* * Retain any non-argument object pushes after the call-in frame (the * exit point may want them) */ walkState.unwindSP = UDATAPointer.cast(callInFrame.subOffset(UDATA .cast(walkState.literals))); - + walkState.frameFlags = callInFrame.specialFrameFlags(); printFrameType(walkState, "JNI call-in"); @@ -1158,17 +1188,15 @@ private void walkJNICallInFrame(WalkState walkState) * The following can only be true if the call-in method has returned * (removed args and pushed return value) */ - + if (!(walkState.walkSP.eq(walkState.unwindSP))) { - if (!walkState.pc.eq(walkState.walkThread.javaVM() - .callInReturnPC().add(3))) { + if (!walkState.pc.eq(walkState.javaVM.callInReturnPC().add(3))) { swPrintf( walkState, 0, "Error: PC should have been advanced in order to push return value, pc = {0}, cipc = {1} !!!", walkState.pc.getHexAddress(), - walkState.walkThread.javaVM() - .callInReturnPC().getHexAddress()); + walkState.javaVM.callInReturnPC().getHexAddress()); } if (walkState.frameFlags.anyBitsIn(J9_SSF_RETURNS_OBJECT)) { swPrintf(walkState, 4, @@ -1184,13 +1212,13 @@ private void walkJNICallInFrame(WalkState walkState) UDATA.cast(walkState.walkSP)), walkState.walkSP.getHexAddress()); } - + walkState.walkSP = walkState.unwindSP; /* * so walkObjectPushes * works correctly */ } - + if (walkState.literals.notNull()) { walkObjectPushes(walkState); } @@ -1198,20 +1226,16 @@ private void walkJNICallInFrame(WalkState walkState) handleOSlotsCorruption(walkState, "StackWalker_29_V0", "walkJNICallInFrame", ex); } } - + if (J9BuildFlags.interp_nativeSupport) { - walkState.walkedEntryLocalStorage = walkState.walkedEntryLocalStorage - .oldEntryLocalStorage(); - walkState.i2jState = walkState.walkedEntryLocalStorage.getAddress() != 0 ? J9I2JStatePointer - .cast(walkState.walkedEntryLocalStorage.i2jStateEA()) - : J9I2JStatePointer.cast(0); - - swPrintf(walkState, 2, "\tNew ELS = {0}", - walkState.walkedEntryLocalStorage.getHexAddress()); + J9VMEntryLocalStoragePointer els = walkState.oldEntryLocalStorage; + walkState.fillElsFields(els); + + swPrintf(walkState, 2, "\tNew ELS = {0}", els.getHexAddress()); } walkState.argCount = new UDATA(0); } - + private void printFrameType(WalkState walkState, String frameType) throws CorruptDataException { @@ -1219,31 +1243,31 @@ private void printFrameType(WalkState walkState, String frameType) walkState, 2, "{0} frame: bp = {1}, sp = {2}, pc = {3}, cp = {4}, arg0EA = {5}, flags = {6}", - frameType, + frameType, walkState.bp.getHexAddress(), - walkState.walkSP.getHexAddress(), + walkState.walkSP.getHexAddress(), walkState.pc.getHexAddress(), walkState.constantPool.getHexAddress(), - walkState.arg0EA.getHexAddress(), + walkState.arg0EA.getHexAddress(), walkState.frameFlags.getHexValue()); swPrintMethod(walkState); } - + private void walkJITJNICalloutFrame(WalkState walkState) throws CorruptDataException { J9SFMethodFramePointer methodFrame = J9SFMethodFramePointer .cast(walkState.walkSP .addOffset(UDATA.cast(walkState.literals))); - + walkState.argCount = new UDATA(0); walkState.bp = UDATAPointer.cast(methodFrame.savedA0EA()); walkState.frameFlags = methodFrame.specialFrameFlags(); walkState.method = methodFrame.method(); walkState.constantPool = ConstantPoolHelpers.J9_CP_FROM_METHOD(walkState.method); - + printFrameType(walkState, "JIT JNI call-out"); - + if ((walkState.flags & J9_STACKWALK_ITERATE_O_SLOTS) != 0) { try { WALK_METHOD_CLASS(walkState); @@ -1255,14 +1279,14 @@ private void walkJITJNICalloutFrame(WalkState walkState) } } } - + private void walkJITResolveFrame(WalkState walkState) throws CorruptDataException { J9SFJITResolveFramePointer jitResolveFrame = J9SFJITResolveFramePointer .cast(walkState.walkSP .addOffset(UDATA.cast(walkState.literals))); - + walkState.argCount = new UDATA(0); walkState.bp = UDATAPointer.cast(jitResolveFrame .taggedRegularReturnSPEA()); @@ -1270,14 +1294,14 @@ private void walkJITResolveFrame(WalkState walkState) try { printFrameType(walkState, "JIT resolve"); - + if ((walkState.flags & J9_STACKWALK_ITERATE_O_SLOTS) != 0) { PointerPointer savedJITExceptionSlot = jitResolveFrame .savedJITExceptionEA(); - + swPrintf(walkState, 4, "\tObject push (savedJITException)"); WALK_O_SLOT(walkState, savedJITExceptionSlot); - + if (walkState.literals.notNull()) { walkObjectPushes(walkState); } @@ -1285,16 +1309,16 @@ private void walkJITResolveFrame(WalkState walkState) } catch (CorruptDataException ex) { handleOSlotsCorruption(walkState, "StackWalker_29_V0", "walkJITResolveFrame", ex); } - + } - + private void walkGenericSpecialFrame(WalkState walkState) throws CorruptDataException { J9SFSpecialFramePointer specialFrame = J9SFSpecialFramePointer .cast(walkState.walkSP .addOffset(UDATA.cast(walkState.literals))); - + walkState.bp = UDATAPointer.cast(specialFrame.savedA0EA()); walkState.frameFlags = specialFrame.specialFrameFlags(); @@ -1308,9 +1332,8 @@ private void walkGenericSpecialFrame(WalkState walkState) handleOSlotsCorruption(walkState, "StackWalker_29_V0", "walkGenericSpecialFrame", ex); } } - + walkState.argCount = new UDATA(0); } - } } diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalkerUtils.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalkerUtils.java index 1d1e85c23bc..af67463aeb1 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalkerUtils.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/StackWalkerUtils.java @@ -42,9 +42,11 @@ import com.ibm.j9ddr.vm29.pointer.UDATAPointer; import com.ibm.j9ddr.vm29.pointer.VoidPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9BuildFlags; +import com.ibm.j9ddr.vm29.pointer.generated.J9I2JStatePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9MethodPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9ROMMethodPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9UTF8Pointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9VMEntryLocalStoragePointer; import com.ibm.j9ddr.vm29.pointer.helper.J9UTF8Helper; import com.ibm.j9ddr.vm29.types.UDATA; @@ -129,7 +131,7 @@ public static void swPrintf(WalkState walkState, int level, // Print output for !stack debugging commands to the printstream. if( messageLevel >= level && messageStream != null ) { String output = MessageFormat.format("<" - + Long.toHexString(walkState.walkThread.getAddress()) + + Long.toHexString(walkState.threadAddress) + "> " + message, args); messageStream.println(output); } @@ -141,7 +143,7 @@ public static void swPrintf(WalkState walkState, int level, /* Initial check to avoid marshalling the arguments if we don't have to */ if (logger.isLoggable(utilLoggingLevel)) { logger.logp(utilLoggingLevel, null, null, "<" - + Long.toHexString(walkState.walkThread.getAddress()) + + Long.toHexString(walkState.threadAddress) + "> " + message, args); } } @@ -196,7 +198,7 @@ public static void WALK_NAMED_INDIRECT_O_SLOT(WalkState walkState, objectSlot.getHexAddress(), value.getHexValue()); } - walkState.callBacks.objectSlotWalkFunction(walkState.walkThread, walkState, objectSlot, VoidPointer.cast(objectSlot)); + walkState.callBacks.objectSlotWalkFunction(walkState, objectSlot, VoidPointer.cast(objectSlot)); } public static void WALK_NAMED_INDIRECT_I_SLOT(WalkState walkState, @@ -263,7 +265,7 @@ public static UDATA JIT_RESOLVE_PARM(WalkState walkState, int parmNumber) throws if (J9BuildFlags.arch_x86 && !J9BuildFlags.env_data64) { return walkState.bp.at(parmNumber); } else { - return walkState.walkedEntryLocalStorage.jitGlobalStorageBase().at(jitArgumentRegisterNumbers[parmNumber - 1]); + return walkState.jitGlobalStorageBase.at(jitArgumentRegisterNumbers[parmNumber - 1]); } } @@ -289,11 +291,11 @@ public static void handleOSlotsCorruption(WalkState walkState, String className, { if (oslotsCorruptionThreshold > 0) { oslotsCorruptionThreshold--; - raiseCorruptDataEvent("CorruptData encountered iterating o-slots. walkThread = " + walkState.walkThread.getHexAddress(), ex, false); + raiseCorruptDataEvent("CorruptData encountered iterating o-slots. walkThread = " + walkState.getThreadHexAddress(), ex, false); } if (oslotsCorruptionThreshold == 0) { - raiseCorruptDataEvent("Corruption threshold hit. Will stop walking object slots on this thread. walkThread = " + walkState.walkThread.getHexAddress(), ex, false); + raiseCorruptDataEvent("Corruption threshold hit. Will stop walking object slots on this thread. walkThread = " + walkState.getThreadHexAddress(), ex, false); walkState.flags &= ~(J9_STACKWALK_ITERATE_O_SLOTS | J9_STACKWALK_MAINTAIN_REGISTER_MAP); oslotsCorruptionThreshold = -1; } diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/TerseStackWalkerCallbacks.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/TerseStackWalkerCallbacks.java index 2322784b403..943a3e8995d 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/TerseStackWalkerCallbacks.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/TerseStackWalkerCallbacks.java @@ -34,16 +34,15 @@ import com.ibm.j9ddr.vm29.pointer.generated.J9MethodPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9ROMMethodPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9UTF8Pointer; -import com.ibm.j9ddr.vm29.pointer.generated.J9VMThreadPointer; import com.ibm.j9ddr.vm29.pointer.helper.J9UTF8Helper; import com.ibm.j9ddr.vm29.j9.ConstantPoolHelpers; -import com.ibm.j9ddr.vm29.j9.stackwalker.StackWalkerUtils; public class TerseStackWalkerCallbacks implements IStackWalkerCallbacks { - public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkState walkState) + @Override + public FrameCallbackResult frameWalkFunction(WalkState walkState) { - + try { if (walkState.method.notNull()) { J9MethodPointer method = walkState.method; @@ -66,8 +65,8 @@ public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkS StackWalkerUtils.swPrintf(walkState, 0, "\t MethodType frame"); } else { if (walkState.pc.getAddress() > J9SF_MAX_SPECIAL_FRAME_TYPE) { - if (walkState.pc.getAddress() == walkState.walkThread.javaVM().callInReturnPC().getAddress() || - walkState.pc.getAddress() == (walkState.walkThread.javaVM().callInReturnPC().getAddress() + 3)) { + if (walkState.pc.getAddress() == walkState.javaVM.callInReturnPC().getAddress() || + walkState.pc.getAddress() == (walkState.javaVM.callInReturnPC().getAddress() + 3)) { StackWalkerUtils.swPrintf(walkState, 0, "\t JNI call-in frame"); } else { StackWalkerUtils.swPrintf(walkState, 0, "\t unknown frame type {0} *{1}", @@ -86,12 +85,14 @@ public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkS return FrameCallbackResult.KEEP_ITERATING; } - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, PointerPointer objectSlot, VoidPointer stackLocation) + @Override + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackLocation) { } - public void fieldSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation) + @Override + public void fieldSlotWalkFunction(WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation) { } diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/WalkState.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/WalkState.java index 83f2d4503ef..e3137846d63 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/WalkState.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/stackwalker/WalkState.java @@ -21,6 +21,8 @@ *******************************************************************************/ package com.ibm.j9ddr.vm29.j9.stackwalker; +import com.ibm.j9ddr.CorruptDataException; +import com.ibm.j9ddr.corereaders.osthread.IOSThread; import com.ibm.j9ddr.vm29.pointer.Pointer; import com.ibm.j9ddr.vm29.pointer.PointerPointer; import com.ibm.j9ddr.vm29.pointer.U8Pointer; @@ -29,16 +31,17 @@ import com.ibm.j9ddr.vm29.pointer.generated.J9I2JStatePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9JITDecompilationInfoPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9JITExceptionTablePointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9MethodPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9VMEntryLocalStoragePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9VMThreadPointer; import com.ibm.j9ddr.vm29.types.UDATA; -import static com.ibm.j9ddr.vm29.structure.J9StackWalkConstants.*; +import static com.ibm.j9ddr.vm29.structure.J9StackWalkConstants.J9SW_POTENTIAL_SAVED_REGISTERS; /** * Mutable java equivalent of J9StackWalkState - * + * * @author andhall * */ @@ -48,100 +51,130 @@ public class WalkState /** Thread to be walked */ public J9VMThreadPointer walkThread; + public J9JavaVMPointer javaVM; + + public long threadAddress; + + public IOSThread osThread; + + public UDATA privateFlags; + /** Flags controlling the walk - * @see StackWalkerConstants + * @see StackWalkerConstants */ public long flags; - + /** Base pointer */ public UDATAPointer bp; - + public UDATAPointer unwindSP; - + /** Program counter */ public U8Pointer pc; - + /** Top-of-stack pointer */ public UDATAPointer sp; - + /** Address of argument 0 */ public UDATAPointer arg0EA; - + public J9MethodPointer literals; - + public UDATAPointer walkSP; - + public UDATA argCount; - + public J9ConstantPoolPointer constantPool; - + public J9MethodPointer method; - + public J9JITExceptionTablePointer jitInfo = J9JITExceptionTablePointer.NULL; - + public UDATA frameFlags; - + public UDATA resolveFrameFlags; - + public UDATAPointer searchValue; - + public int skipCount; - + public long maxFrames; - + /* User data excluded. If you want to add your own fields, create a subclass */ - + public long framesWalked; - + public IStackWalkerCallbacks callBacks; - + /* Cache isn't duplicated in offline walker */ - + public Pointer restartPoint; - + public Pointer restartException; - + public Pointer inlinerMap; - + public long inlineDepth; - + public UDATAPointer cacheCursor; - + public J9JITDecompilationInfoPointer decompilationRecord; - + public boolean searchFrameFound; - + public UDATAPointer registerEAs[]; - + { registerEAs = new UDATAPointer[(int) J9SW_POTENTIAL_SAVED_REGISTERS]; - + for (int i=0; i < registerEAs.length; i++) { registerEAs[i] = UDATAPointer.NULL; } } - - public J9VMEntryLocalStoragePointer walkedEntryLocalStorage; - + + public J9VMEntryLocalStoragePointer oldEntryLocalStorage; + + public UDATAPointer jitGlobalStorageBase; + + public UDATAPointer jitFPRegisterStorageBase; + public J9I2JStatePointer i2jState; - + public J9JITDecompilationInfoPointer decompilationStack; - + public PointerPointer pcAddress; - + public UDATA outgoingArgCount; - + public U8Pointer objectSlotBitVector; - + public UDATA elsBitVector; - + public U8Pointer bytecodePCOffset; - + public UDATAPointer j2iFrame; - + public UDATA previousFrameFlags; - + public int slotIndex; - + public int slotType; + + public String getThreadHexAddress() { + return String.format("0x%0" + (UDATA.SIZEOF * 2) + "X", threadAddress); + } + + public void fillElsFields(J9VMEntryLocalStoragePointer els) throws CorruptDataException { + if (els.notNull()) { + i2jState = els.i2jState(); + jitGlobalStorageBase = els.jitGlobalStorageBase(); + jitFPRegisterStorageBase = els.jitFPRegisterStorageBase(); + oldEntryLocalStorage = els.oldEntryLocalStorage(); + } else { + i2jState = J9I2JStatePointer.NULL; + jitGlobalStorageBase = UDATAPointer.NULL; + jitFPRegisterStorageBase = UDATAPointer.NULL; + oldEntryLocalStorage = J9VMEntryLocalStoragePointer.NULL; + } + } } diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java index fc574fca5fc..f2f670c0641 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/GetCommandsTask.java @@ -37,6 +37,7 @@ import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.ClassForNameCommand; import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.ClassloadersSummaryCommand; import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.CompressedRefMappingCommand; +import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.ContinuationStackWalkCommand; import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.CoreInfoCommand; import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllClassesInModuleCommand; import com.ibm.j9ddr.vm29.tools.ddrinteractive.commands.DumpAllClassloadersCommand; @@ -200,6 +201,7 @@ public void run(IVMData vmData, Object[] userData) if (J9ConstantPoolCommand.isSupported()) { toPassBack.add(new J9ConstantPoolCommand()); } + toPassBack.add(new ContinuationStackWalkCommand()); if (ValueTypeHelper.getValueTypeHelper().areValueTypesSupported()) { toPassBack.add(new FlatObjectCommand()); diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/ContinuationStackWalkCommand.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/ContinuationStackWalkCommand.java new file mode 100644 index 00000000000..d5407f7acc2 --- /dev/null +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/ContinuationStackWalkCommand.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright IBM Corp. and others 2023 + * + * This program and the accompanying materials are made available under + * the terms of the Eclipse Public License 2.0 which accompanies this + * distribution and is available at https://www.eclipse.org/legal/epl-2.0/ + * or the Apache License, Version 2.0 which accompanies this distribution and + * is available at https://www.apache.org/licenses/LICENSE-2.0. + * + * This Source Code may also be made available under the following + * Secondary Licenses when the conditions for such availability set + * forth in the Eclipse Public License, v. 2.0 are satisfied: GNU + * General Public License, version 2 with the GNU Classpath + * Exception [1] and GNU General Public License, version 2 with the + * OpenJDK Assembly Exception [2]. + * + * [1] https://www.gnu.org/software/classpath/license.html + * [2] https://openjdk.org/legal/assembly-exception.html + * + * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0 + *******************************************************************************/ +package com.ibm.j9ddr.vm29.tools.ddrinteractive.commands; + +import java.io.PrintStream; + +import com.ibm.j9ddr.CorruptDataException; +import com.ibm.j9ddr.tools.ddrinteractive.Command; +import com.ibm.j9ddr.tools.ddrinteractive.CommandUtils; +import com.ibm.j9ddr.tools.ddrinteractive.Context; +import com.ibm.j9ddr.tools.ddrinteractive.DDRInteractiveCommandException; +import com.ibm.j9ddr.vm29.j9.DataType; +import com.ibm.j9ddr.vm29.j9.stackwalker.BaseStackWalkerCallbacks; +import com.ibm.j9ddr.vm29.j9.stackwalker.StackWalkResult; +import com.ibm.j9ddr.vm29.j9.stackwalker.StackWalker; +import com.ibm.j9ddr.vm29.j9.stackwalker.StackWalkerUtils; +import com.ibm.j9ddr.vm29.j9.stackwalker.TerseStackWalkerCallbacks; +import com.ibm.j9ddr.vm29.j9.stackwalker.WalkState; +import com.ibm.j9ddr.vm29.pointer.generated.J9BuildFlags; +import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer; +import com.ibm.j9ddr.vm29.pointer.helper.J9RASHelper; +import com.ibm.j9ddr.vm29.structure.J9Consts; +import com.ibm.j9ddr.vm29.tools.ddrinteractive.JavaVersionHelper; + +/** + * DDR command to walk the stack frames of a continuation. + */ +public class ContinuationStackWalkCommand extends Command { + public ContinuationStackWalkCommand() { + addCommand("continuationstack", "", "Walks the Java stack for "); + addCommand("continuationstackslots", "", "Walks the Java stack (including objects) for "); + } + + @Override + public void run(String command, String[] args, Context context, PrintStream out) throws DDRInteractiveCommandException { + try { + final J9JavaVMPointer vm = J9RASHelper.getVM(DataType.getJ9RASPointer()); + + if (!JavaVersionHelper.ensureMinimumJavaVersion(19, vm, out)) { + return; + } + + if (args.length != 1) { + CommandUtils.dbgPrint(out, "Exactly one argument (address) must be provided.\n"); + return; + } + long address = CommandUtils.parsePointer(args[0], J9BuildFlags.env_data64); + if (0 == address) { + CommandUtils.dbgPrint(out, "Address must be non-zero.\n"); + return; + } + + StackWalkerUtils.enableVerboseLogging(3, out); + + WalkState walkState = new WalkState(); + + walkState.flags = J9Consts.J9_STACKWALK_RECORD_BYTECODE_PC_OFFSET; + + if (command.equalsIgnoreCase("!continuationstackslots")) { + walkState.flags |= J9Consts.J9_STACKWALK_ITERATE_O_SLOTS; + // 100 is highly arbitrary but basically means "print everything". + // It is used in jextract where the message levels have been copied + // from to begin with, so it should mean we get the same output. + StackWalkerUtils.enableVerboseLogging(100, out); + walkState.callBacks = new BaseStackWalkerCallbacks(); + } else { + StackWalkerUtils.enableVerboseLogging(0, out); + walkState.callBacks = new TerseStackWalkerCallbacks(); + walkState.flags |= J9Consts.J9_STACKWALK_ITERATE_FRAMES; + } + + StackWalkResult result = StackWalker.walkStackFrames(walkState, address); + + if (result != StackWalkResult.NONE) { + out.println("Stack walk result: " + result); + } + + StackWalkerUtils.disableVerboseLogging(); + + out.flush(); + } catch (CorruptDataException e) { + throw new DDRInteractiveCommandException(e); + } + } +} diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/JitstackCommand.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/JitstackCommand.java index a4992f2b179..90f17f7dd85 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/JitstackCommand.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/JitstackCommand.java @@ -112,12 +112,17 @@ public void run(String command, String[] args, Context context, PrintStream out) } walkState.walkThread = thread; + walkState.sp = sp; + walkState.arg0EA = arg0EA; + walkState.pc = pc; + walkState.literals = literals; walkState.callBacks = new BaseStackWalkerCallbacks(); walkState.frameFlags = new UDATA(0); + walkState.fillElsFields(entryLocalStorage); - StackWalkResult result = StackWalker.walkStackFrames(walkState, sp, arg0EA, pc, literals, entryLocalStorage); + StackWalkResult result = StackWalker.walkStackFrames(walkState); - if (result != StackWalkResult.NONE ) { + if (result != StackWalkResult.NONE) { out.println("Stack walk result: " + result); } diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/StackWalkCommand.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/StackWalkCommand.java index 3a77f0906b5..9af7c31542b 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/StackWalkCommand.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/commands/StackWalkCommand.java @@ -45,7 +45,7 @@ import com.ibm.j9ddr.vm29.pointer.generated.J9VMEntryLocalStoragePointer; import com.ibm.j9ddr.vm29.pointer.generated.J9VMThreadPointer; -public class StackWalkCommand extends Command +public class StackWalkCommand extends Command { public StackWalkCommand() @@ -53,8 +53,8 @@ public StackWalkCommand() addCommand("stack", "", "Walks the Java stack for "); addCommand("stackslots", "", "Walks the Java stack (including objects) for "); } - - public void run(String command, String[] args, Context context, PrintStream out) throws DDRInteractiveCommandException + + public void run(String command, String[] args, Context context, PrintStream out) throws DDRInteractiveCommandException { try { UDATAPointer sp = UDATAPointer.NULL; @@ -62,8 +62,8 @@ public void run(String command, String[] args, Context context, PrintStream out) U8Pointer pc = U8Pointer.NULL; J9MethodPointer literals = J9MethodPointer.NULL; J9VMEntryLocalStoragePointer entryLocalStorage = J9VMEntryLocalStoragePointer.NULL; - - String[] realArgs = null; + + String[] realArgs = null; if (args.length != 0) { realArgs = args[0].split(","); } @@ -92,14 +92,14 @@ public void run(String command, String[] args, Context context, PrintStream out) WalkState walkState = new WalkState(); walkState.flags = J9_STACKWALK_RECORD_BYTECODE_PC_OFFSET; - + if (realArgs.length >= 5) { address = CommandUtils.parsePointer(realArgs[1], J9BuildFlags.env_data64); sp = UDATAPointer.cast(address); - + address = CommandUtils.parsePointer(realArgs[2], J9BuildFlags.env_data64); arg0EA = UDATAPointer.cast(address); - + address = CommandUtils.parsePointer(realArgs[3], J9BuildFlags.env_data64); pc = U8Pointer.cast(address); @@ -120,7 +120,7 @@ public void run(String command, String[] args, Context context, PrintStream out) entryLocalStorage = thread.entryLocalStorage(); } } - + if (command.equalsIgnoreCase("!stackslots")) { walkState.flags |= J9_STACKWALK_ITERATE_O_SLOTS; // 100 is highly arbitrary but basically means "print everything". @@ -128,17 +128,22 @@ public void run(String command, String[] args, Context context, PrintStream out) // from to begin with, so it should mean we get the same output. StackWalkerUtils.enableVerboseLogging(100, out); walkState.callBacks = new BaseStackWalkerCallbacks(); - } else { + } else { StackWalkerUtils.enableVerboseLogging(0, out); walkState.callBacks = new TerseStackWalkerCallbacks(); walkState.flags |= J9_STACKWALK_ITERATE_FRAMES; } walkState.walkThread = thread; + walkState.walkSP = sp; + walkState.arg0EA = arg0EA; + walkState.pc = pc; + walkState.literals = literals; + walkState.fillElsFields(entryLocalStorage); - StackWalkResult result = StackWalker.walkStackFrames(walkState, sp, arg0EA, pc, literals, entryLocalStorage); + StackWalkResult result = StackWalker.walkStackFrames(walkState); - if (result != StackWalkResult.NONE ) { + if (result != StackWalkResult.NONE) { out.println("Stack walk result: " + result); } @@ -149,6 +154,4 @@ public void run(String command, String[] args, Context context, PrintStream out) throw new DDRInteractiveCommandException(e); } } - - } diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/gccheck/CheckVMThreadStacks.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/gccheck/CheckVMThreadStacks.java index de898daeec6..59496fca672 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/gccheck/CheckVMThreadStacks.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/gccheck/CheckVMThreadStacks.java @@ -58,7 +58,8 @@ public void check() walkState.callBacks = new BaseStackWalkerCallbacks() { - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) + @Override + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) { _engine.checkSlotStack(objectSlot, walkThread, stackAddress); } @@ -93,7 +94,8 @@ public void print() walkState.callBacks = new BaseStackWalkerCallbacks() { - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) + @Override + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) { try { formatter.entry(objectSlot.at(0)); @@ -125,7 +127,8 @@ private void dumpStackTrace(J9VMThreadPointer walkThread) walkState.callBacks = new BaseStackWalkerCallbacks() { - public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkState walkState) + @Override + public FrameCallbackResult frameWalkFunction(WalkState walkState) { String className = "(unknown class)"; if(walkState.constantPool.notNull()) { diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/view/dtfj/java/DTFJJavaThread.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/view/dtfj/java/DTFJJavaThread.java index c78cba16192..9c92da80737 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/view/dtfj/java/DTFJJavaThread.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/view/dtfj/java/DTFJJavaThread.java @@ -227,7 +227,8 @@ private class StackWalkerCallbacks extends BaseStackWalkerCallbacks implements I { private Object frame = null; - public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkState walkState) + @Override + public FrameCallbackResult frameWalkFunction(WalkState walkState) { if (walkState.method.isNull()){ return FrameCallbackResult.KEEP_ITERATING; @@ -243,7 +244,8 @@ public FrameCallbackResult frameWalkFunction(J9VMThreadPointer walkThread, WalkS return FrameCallbackResult.KEEP_ITERATING; } - public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) + @Override + public void objectSlotWalkFunction(WalkState walkState, PointerPointer objectSlot, VoidPointer stackAddress) { if (walkState.method.isNull()){ /* adding an object slot iterator causes us to be called for @@ -268,9 +270,8 @@ public void objectSlotWalkFunction(J9VMThreadPointer walkThread, WalkState walkS } } - - public void fieldSlotWalkFunction(J9VMThreadPointer walkThread, - WalkState walkState, ObjectReferencePointer objectSlot, + @Override + public void fieldSlotWalkFunction(WalkState walkState, ObjectReferencePointer objectSlot, VoidPointer stackLocation) { if (walkState.method.isNull()){ @@ -375,7 +376,7 @@ private void walkStack() unregister((IEventListener)walkState.callBacks); if(result != StackWalkResult.NONE) { - frames.add(J9DDRDTFJUtils.newCorruptData(DTFJContext.getProcess(), "Bad return from stack walker walking thread 0x" + Long.toHexString(walkState.walkThread.getAddress()) + ". Some stack frames may be missing. Final state = " + result)); + frames.add(J9DDRDTFJUtils.newCorruptData(DTFJContext.getProcess(), "Bad return from stack walker walking thread 0x" + Long.toHexString(walkState.threadAddress) + ". Some stack frames may be missing. Final state = " + result)); } } diff --git a/runtime/ddr/vmddr.cpp b/runtime/ddr/vmddr.cpp index 11e11f091b4..ae0d04ec7c6 100644 --- a/runtime/ddr/vmddr.cpp +++ b/runtime/ddr/vmddr.cpp @@ -63,6 +63,7 @@ VM_DdrDebugLink(J9IndexableObjectWithDataAddressDiscontiguousCompressed) VM_DdrDebugLink(J9IndexableObjectWithDataAddressDiscontiguousFull) VM_DdrDebugLink(J9JITDataCacheHeader) VM_DdrDebugLink(J9JITFrame) +VM_DdrDebugLink(J9JITGPRSpillArea) VM_DdrDebugLink(J9JITHashTable) VM_DdrDebugLink(J9JITStackAtlas) VM_DdrDebugLink(J9Object) diff --git a/test/functional/DDR_Test/src/j9vm/test/ddrext/junit/TestThread.java b/test/functional/DDR_Test/src/j9vm/test/ddrext/junit/TestThread.java index 2d40d122923..eaab3283efd 100644 --- a/test/functional/DDR_Test/src/j9vm/test/ddrext/junit/TestThread.java +++ b/test/functional/DDR_Test/src/j9vm/test/ddrext/junit/TestThread.java @@ -49,10 +49,10 @@ public void testStack() { Constants.STACK_FAILURE_KEY, true)); } - /* - * tests !stackslots extension with all options !stackslots thread - * !stackslots thread,sp,a0,pc,literals !stackslots - * thread,sp,a0,pc,literals,els + /** + * Tests !stackslots extension with all options: + * !stackslots thread + * !stackslots thread,sp,a0,pc,literals */ public void testStackSlots() { String threadOutput = exec(Constants.THREAD_CMD, new String[0]); @@ -72,8 +72,7 @@ public void testStackSlots() { Constants.STACKSLOTS_FAILURE_KEY, true)); /* test !stackslots thread,sp,a0,pc,literals */ - String paramSet1 = getStackSlotsParamSet(stackSlotsOutput, - threadAddress, false); + String paramSet1 = getStackSlotsParamSet(stackSlotsOutput, threadAddress); if (paramSet1 == null) { fail("Failed to construct parameter list for command : !stackslots thread,sp,a0,pc,literals\nStackSlots Output being used : \n" + stackSlotsOutput); @@ -84,20 +83,6 @@ public void testStackSlots() { Constants.STACKSLOTS_SUCCESS_KEY, Constants.STACKSLOTS_FAILURE_KEY, true)); } - - /* test !stackslots thread,sp,a0,pc,literals,els */ - String paramSet2 = getStackSlotsParamSet(stackSlotsOutput, - threadAddress, true); - if (paramSet2 == null) { - fail("Failed to construct parameter list for command : !stackslots thread,sp,a0,pc,literals,els\nStackSlots Output being used : \n" - + stackSlotsOutput); - } else { - String stackSlotsOutputParam2 = exec(Constants.STACKSLOTS_CMD, - new String[] { paramSet2 }); - assertTrue(validate(stackSlotsOutputParam2, - Constants.STACKSLOTS_SUCCESS_KEY, - Constants.STACKSLOTS_FAILURE_KEY, true)); - } } public void testJ9VMThread() { @@ -238,48 +223,38 @@ private String getStackSlotsValues(String stackslotOutput) { return results; } - /* - * If needELS, we return the second param list for stackslots: - * thread,sp,a0,pc,literals,elsElse,we return the first param list for - * stackslots : thread,sp,a0,pc,literals + /** + * Constructs the parameter list of stackslots (thread, sp, a0, pc, literals) from the output. + * @param stackOutput the output of the stackslots command + * @param threadAddress the address of the walked thread + * @return the parameter list for stackslots, or null if it failed to construct the list */ - private String getStackSlotsParamSet(String stackOutput, - String threadAddress, boolean needELS) { - String output[] = stackOutput.split(Constants.NL); + private static String getStackSlotsParamSet(String stackOutput, String threadAddress) { + String[] output = stackOutput.split(Constants.NL); String paramList = threadAddress; for (String aLine : output) { if (aLine.contains("Initial values")) { - String sp = null, pc = null, literals = null, a0 = null, els = null; - String tokens[] = aLine.split(","); - for (int i = 0; i < tokens.length; i++) { - String token = tokens[i].trim(); + String sp = null; + String pc = null; + String literals = null; + String a0 = null; + String[] tokens = aLine.split(","); + for (String token : tokens) { + token = token.trim(); if (token.contains("walkSP")) { - sp = tokens[i].split("=")[1].trim(); + sp = token.split("=")[1].trim(); } else if (token.startsWith("PC")) { pc = token.split("=")[1].trim(); } else if (token.startsWith("literals")) { literals = token.split("=")[1].trim(); } else if (token.startsWith("A0")) { a0 = token.split("=")[1].trim(); - } else if (token.startsWith("ELS")) { - els = token.split("=")[1].trim(); } } - if (needELS) { - if (sp == null || a0 == null || pc == null - || literals == null || els == null) { - return null; - } - return paramList + "," + sp + "," + a0 + "," + pc + "," - + literals + "," + els; - } else { - if (sp == null || a0 == null || pc == null - || literals == null) { - return null; - } - return paramList + "," + sp + "," + a0 + "," + pc + "," - + literals; + if (sp == null || a0 == null || pc == null || literals == null) { + return null; } + return paramList + "," + sp + "," + a0 + "," + pc + "," + literals; } } return null;