Skip to content

Commit

Permalink
Merge pull request #17174 from thallium/vthread-0.37
Browse files Browse the repository at this point in the history
(0.37) Add DDR command !vthreads
  • Loading branch information
pshipton authored Apr 12, 2023
2 parents 5db9c94 + ebada58 commit 7585aa4
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 17 deletions.
6 changes: 5 additions & 1 deletion debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2021, 2022 IBM Corp. and others
* Copyright (c) 2021, 2023 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -621,12 +621,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
Expand Down Expand Up @@ -709,6 +712,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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2001, 2021 IBM Corp. and others
* Copyright (c) 2001, 2023 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -404,7 +404,7 @@ public static J9ObjectPointer getObjectField(J9ObjectPointer objPointer, J9Objec
}
}

private static J9ObjectFieldOffset getFieldOffset(J9ObjectPointer objPointer, String name, String signature) throws CorruptDataException
public static J9ObjectFieldOffset getFieldOffset(J9ObjectPointer objPointer, String name, String signature) throws CorruptDataException
{
J9ObjectFieldOffset result = J9ClassHelper.checkFieldOffsetCache(J9ObjectHelper.clazz(objPointer), name, signature);
if (result == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2010, 2022 IBM Corp. and others
* Copyright (c) 2010, 2023 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -204,6 +204,7 @@ public void run(IVMData vmData, Object[] userData)
if (ValueTypeHelper.getValueTypeHelper().areValueTypesSupported()) {
toPassBack.add(new FlatObjectCommand());
}
toPassBack.add(new VirtualThreadsCommand());

loadPlugins(toPassBack, loader);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2018 IBM Corp. and others
* Copyright (c) 2018, 2023 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand All @@ -25,30 +25,43 @@

import com.ibm.j9ddr.CorruptDataException;
import com.ibm.j9ddr.vm29.pointer.generated.J9JavaVMPointer;
import com.ibm.j9ddr.vm29.types.UDATA;

/**
* JavaVersionHelper helps check if the JVM version is new enough for the modularity DDR commands
*/
public class JavaVersionHelper
{
public final static int J2SE_SERVICE_RELEASE_MASK = 0xFFFF;
public final static int J2SE_19 = 9;
public final static int J2SE_JAVA_SPEC_VERSION_SHIFT = 8;
private final static int J2SE_SERVICE_RELEASE_MASK = 0xFFFF;
private final static int J2SE_JAVA_SPEC_VERSION_SHIFT = 8;

/**
* Returns true if the Java version is Java9 and up.
* Returns {@code true} if the Java version is Java9 or higher.
* @param vm J9JavaVMPointer
* @param out The output print stream
* @return if the Java version is Java9 and up or not.
* @param out the output print stream
* @return {@code true} if the Java version is Java9 or higher
* @throws CorruptDataException
* @deprecated use {@link #ensureMinimumJavaVersion(int, J9JavaVMPointer, PrintStream)} instead
*/
public static boolean ensureJava9AndUp(J9JavaVMPointer vm, PrintStream out) throws CorruptDataException
@Deprecated
public static boolean ensureJava9AndUp(J9JavaVMPointer vm, PrintStream out) throws CorruptDataException
{
int javaVersion = vm.j2seVersion().bitAnd(J2SE_SERVICE_RELEASE_MASK).intValue() >> J2SE_JAVA_SPEC_VERSION_SHIFT;
if (javaVersion < J2SE_19) {
out.printf("This command only works with core file created by VM with Java version 9 or higher%n"
+ "The current VM Java version is: %s%n", javaVersion);
return ensureMinimumJavaVersion(9, vm, out);
}

/**
* Returns {@code true} if the Java version is {@code version} or higher.
* @param version the minimum version
* @param vm J9JavaVMPointer
* @param out the output print stream
* @return {@code true} if the Java version is {@code version} or higher
* @throws CorruptDataException
*/
public static boolean ensureMinimumJavaVersion(int version, J9JavaVMPointer vm, PrintStream out) throws CorruptDataException
{
int javaVersion = vm.j2seVersion().bitAnd(J2SE_SERVICE_RELEASE_MASK).rightShift(J2SE_JAVA_SPEC_VERSION_SHIFT).intValue();
if (javaVersion < version) {
out.printf("This command only works with core file created by VM with Java version %d or higher.%n"
+ "The current VM Java version is: %s.%n", version, javaVersion);
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*******************************************************************************
* Copyright (c) 2022, 2023 IBM Corp. and others
*
* 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 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
package com.ibm.j9ddr.vm29.tools.ddrinteractive;

import java.io.PrintStream;

import com.ibm.j9ddr.CorruptDataException;
import com.ibm.j9ddr.tools.ddrinteractive.Command;
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.J9ObjectFieldOffset;
import com.ibm.j9ddr.vm29.j9.gc.GCBase;
import com.ibm.j9ddr.vm29.pointer.ObjectReferencePointer;
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;

/**
* vthreads command lists all the virtual threads.
*
* Example:
* !vthreads
* Example output:
* !continuationstack 0x00007fe78c0f9600 !j9vmcontinuation 0x00007fe78c0f9600 !j9object 0x0000000706401588 (Continuation) !j9object 0x0000000706400FB0 (VThread) - name1
* !continuationstack 0x00007fe78c23aa80 !j9vmcontinuation 0x00007fe78c23aa80 !j9object 0x0000000706424F90 (Continuation) !j9object 0x0000000706424EF0 (VThread) - name2
* !continuationstack 0x00007fe78c244ac0 !j9vmcontinuation 0x00007fe78c244ac0 !j9object 0x00000007064250D8 (Continuation) !j9object 0x0000000706425038 (VThread) - name3
* ...
*/
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");
}

@Override
public void run(String command, String[] args, Context context, PrintStream out) throws DDRInteractiveCommandException {
try {
J9JavaVMPointer vm = J9RASHelper.getVM(DataType.getJ9RASPointer());
if (JavaVersionHelper.ensureMinimumJavaVersion(19, vm, out)) {
displayVirtualThreads(vm, out);
}
} catch (CorruptDataException | NoSuchFieldException e) {
throw new DDRInteractiveCommandException(e);
}
}

/**
* Prints all the live virtual threads.
*
* @param vm the J9JavaVMPointer of the virtual machine
* @param out the PrintStream to write output to
*/
private static void displayVirtualThreads(J9JavaVMPointer vm, PrintStream out) throws CorruptDataException, NoSuchFieldException {
String addressFormat = "0x%0" + (UDATA.SIZEOF * 2) + "x";
String outputFormat = "!continuationstack " + addressFormat
+ " !j9vmcontinuation " + addressFormat
+ " !j9object %s (Continuation) !j9object %s (VThread) - %s%n";
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();
}
}
}
1 change: 1 addition & 0 deletions runtime/rasdump/trigger.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down

0 comments on commit 7585aa4

Please sign in to comment.