From 5d0db8bb0ef82515e0883ce76737ed39acf17a51 Mon Sep 17 00:00:00 2001 From: Gengchen Tuo Date: Mon, 3 Apr 2023 14:36:54 -0400 Subject: [PATCH] Update !vthread command to use GC continuation list Fixes https://github.com/eclipse-openj9/openj9/issues/17084 Signed-off-by: Gengchen Tuo --- .../src/com/ibm/j9ddr/AuxFieldInfo29.dat | 6 +- .../ddrinteractive/VirtualThreadsCommand.java | 83 +++++++++++-------- runtime/rasdump/trigger.c | 1 + 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat index acfdff64f19..47a14f75a58 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat @@ -267,7 +267,6 @@ J9JavaVM.jitConfig = required J9JavaVM.jniGlobalReferences = required J9JavaVM.jniWeakGlobalReferences = required J9JavaVM.jvmtiData = required -J9JavaVM.liveVirtualThreadList = J9Object** J9JavaVM.longArrayClass = required J9JavaVM.longReflectClass = required J9JavaVM.mainThread = required @@ -286,7 +285,6 @@ J9JavaVM.sharedInvariantInternTable = required J9JavaVM.shortReflectClass = required J9JavaVM.systemClassLoader = required J9JavaVM.systemProperties = required -J9JavaVM.virtualThreadLinkNextOffset = UDATA J9JavaVM.vmArgsArray = required J9JavaVM.voidReflectClass = required J9LineNumber.lineNumber = required @@ -625,12 +623,15 @@ MM_AllocationContextTarok._allocationContextType = required MM_CardTable._cardTableStart = required MM_CardTable._cardTableVirtualStart = required MM_CardTable._heapBase = required +MM_ContinuationObjectList._head = J9Object* +MM_ContinuationObjectList._nextList = MM_ContinuationObjectList* MM_CopyScanCache.cacheAlloc = required MM_CopyScanCache.cacheTop = required MM_EnvironmentStandard._survivorCopyScanCache = required MM_EnvironmentStandard._tenureCopyScanCache = required MM_GCExtensions.accessBarrier = required MM_GCExtensions.collectStringConstants = required +MM_GCExtensions.continuationObjectLists = MM_ContinuationObjectList* MM_GCExtensions.dynamicClassUnloading = required MM_GCExtensions.finalizeListManager = required MM_GCExtensions.ownableSynchronizerObjectLists = required @@ -713,6 +714,7 @@ MM_MemorySpace._name = required MM_MemorySubSpace._memorySpace = required MM_MemorySubSpace._memoryType = required MM_MemorySubSpaceGeneric._memoryPool = required +MM_ObjectAccessBarrier._continuationLinkOffset = UDATA MM_ObjectAccessBarrier._ownableSynchronizerLinkOffset = required MM_ObjectAccessBarrier._referenceLinkOffset = required MM_OwnableSynchronizerObjectList._head = required diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/VirtualThreadsCommand.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/VirtualThreadsCommand.java index 805a20fa483..4774d7f739c 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/VirtualThreadsCommand.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/tools/ddrinteractive/VirtualThreadsCommand.java @@ -29,10 +29,12 @@ import com.ibm.j9ddr.tools.ddrinteractive.DDRInteractiveCommandException; import com.ibm.j9ddr.vm29.j9.DataType; import com.ibm.j9ddr.vm29.j9.J9ObjectFieldOffset; +import com.ibm.j9ddr.vm29.j9.gc.GCBase; import com.ibm.j9ddr.vm29.pointer.ObjectReferencePointer; -import com.ibm.j9ddr.vm29.pointer.PointerPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9ObjectPointer; +import com.ibm.j9ddr.vm29.pointer.generated.MM_ContinuationObjectListPointer; +import com.ibm.j9ddr.vm29.pointer.generated.MM_GCExtensionsPointer; import com.ibm.j9ddr.vm29.pointer.helper.J9ObjectHelper; import com.ibm.j9ddr.vm29.pointer.helper.J9RASHelper; import com.ibm.j9ddr.vm29.types.UDATA; @@ -49,6 +51,31 @@ * ... */ public class VirtualThreadsCommand extends Command { + private static J9ObjectFieldOffset vthreadOffset; + private static J9ObjectFieldOffset vmRefOffset; + private static J9ObjectFieldOffset nameOffset; + + private static J9ObjectPointer getVirtualThread(J9ObjectPointer continuation) throws CorruptDataException { + if (vthreadOffset == null) { + vthreadOffset = J9ObjectHelper.getFieldOffset(continuation, "vthread", "Ljava/lang/Thread;"); + } + return J9ObjectHelper.getObjectField(continuation, vthreadOffset); + } + + private static long getVmRef(J9ObjectPointer continuation) throws CorruptDataException { + if (vmRefOffset == null) { + vmRefOffset = J9ObjectHelper.getFieldOffset(continuation, "vmRef", "J"); + } + return J9ObjectHelper.getLongField(continuation, vmRefOffset); + } + + private static J9ObjectPointer getName(J9ObjectPointer vthread) throws CorruptDataException { + if (nameOffset == null) { + nameOffset = J9ObjectHelper.getFieldOffset(vthread, "name", "Ljava/lang/String;"); + } + return J9ObjectHelper.getObjectField(vthread, nameOffset); + } + public VirtualThreadsCommand() { addCommand("vthreads", "", "Lists virtual threads"); } @@ -72,43 +99,31 @@ public void run(String command, String[] args, Context context, PrintStream out) * @param out the PrintStream to write output to */ private static void displayVirtualThreads(J9JavaVMPointer vm, PrintStream out) throws CorruptDataException, NoSuchFieldException { - PointerPointer mainVirtualThread = vm.liveVirtualThreadList(); - if (mainVirtualThread.isNull()) { - return; - } - - J9ObjectPointer root = J9ObjectPointer.cast(mainVirtualThread.at(0)); - if (root.isNull()) { - return; - } - - UDATA linkNextOffset = vm.virtualThreadLinkNextOffset(); - /* - * liveVirtualThreadList is a circular doubly-linked list storing all the live virtual threads. - * The root node is a dummy virtual thread marking the start and the end of the list. - */ - J9ObjectPointer node = ObjectReferencePointer.cast(root.addOffset(linkNextOffset)).at(0); - J9ObjectFieldOffset nameOffset = J9ObjectHelper.getFieldOffset(node, "name", "Ljava/lang/String;"); - J9ObjectFieldOffset contOffset = J9ObjectHelper.getFieldOffset(node, "cont", "Ljdk/internal/vm/Continuation;"); - J9ObjectPointer cont = J9ObjectHelper.getObjectField(node, contOffset); - J9ObjectFieldOffset vmRefOffset = J9ObjectHelper.getFieldOffset(cont, "vmRef", "J"); - String addressFormat = "0x%0" + (UDATA.SIZEOF * 2) + "x"; String outputFormat = "!continuationstack " + addressFormat + " !j9vmcontinuation " + addressFormat + " !j9object %s (Continuation) !j9object %s (VThread) - %s%n"; - while (!node.eq(root)) { - J9ObjectPointer name = J9ObjectHelper.getObjectField(node, nameOffset); - cont = J9ObjectHelper.getObjectField(node, contOffset); - long vmRef = J9ObjectHelper.getLongField(cont, vmRefOffset); - out.format( - outputFormat, - vmRef, - vmRef, - cont.getHexAddress(), - node.getHexAddress(), - J9ObjectHelper.stringValue(name)); - node = ObjectReferencePointer.cast(node.addOffset(linkNextOffset)).at(0); + MM_GCExtensionsPointer extensions = GCBase.getExtensions(); + UDATA linkOffset = extensions.accessBarrier()._continuationLinkOffset(); + MM_ContinuationObjectListPointer continuationObjectList = extensions.continuationObjectLists(); + + while (continuationObjectList.notNull()) { + J9ObjectPointer continuation = continuationObjectList._head(); + while (continuation.notNull()) { + long vmRef = getVmRef(continuation); + J9ObjectPointer vthread = getVirtualThread(continuation); + J9ObjectPointer name = getName(vthread); + + out.format( + outputFormat, + vmRef, + vmRef, + continuation.getHexAddress(), + vthread.getHexAddress(), + J9ObjectHelper.stringValue(name)); + continuation = ObjectReferencePointer.cast(continuation.addOffset(linkOffset)).at(0); + } + continuationObjectList = continuationObjectList._nextList(); } } } diff --git a/runtime/rasdump/trigger.c b/runtime/rasdump/trigger.c index 05953f71c61..cd6902dc990 100644 --- a/runtime/rasdump/trigger.c +++ b/runtime/rasdump/trigger.c @@ -681,6 +681,7 @@ prepareForDump(struct J9JavaVM *vm, struct J9RASdumpAgent *agent, struct J9RASdu /* If exclusive access has been obtained, do the requested preparation */ if (newState & J9RAS_DUMP_GOT_EXCLUSIVE_VM_ACCESS) { vm->memoryManagerFunctions->j9gc_flush_caches_for_walk(vm); + vm->memoryManagerFunctions->j9gc_flush_nonAllocationCaches_for_walk(vm); newState |= J9RAS_DUMP_HEAP_PREPARED; } }