8242152: SA does not include StackMapTables when dumping .class files

Reviewed-by: cjplummer, sspitsyn
This commit is contained in:
Daohan Qu 2023-06-22 06:45:19 +00:00 committed by Serguei Spitsyn
parent 3bc475ee65
commit 8e047029e8
4 changed files with 60 additions and 0 deletions
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot
test/hotspot/jtreg/serviceability/sa

@ -62,6 +62,7 @@ public class ConstMethod extends Metadata {
private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
Type type = db.lookupType("ConstMethod");
constants = new MetadataField(type.getAddressField("_constants"), 0);
stackMapData = type.getAddressField("_stackmap_data");
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
flags = new CIntField(type.getCIntegerField("_flags._flags"), 0);
@ -108,6 +109,7 @@ public class ConstMethod extends Metadata {
// Fields
private static MetadataField constants;
private static AddressField stackMapData; // Raw stackmap data for the method (#entries + entries)
private static CIntField constMethodSize;
private static CIntField flags;
private static CIntField codeSize;
@ -136,6 +138,15 @@ public class ConstMethod extends Metadata {
return (ConstantPool) constants.getValue(this);
}
public boolean hasStackMapTable() {
return stackMapData.getValue(getAddress()) != null;
}
public U1Array getStackMapData() {
Address addr = stackMapData.getValue(getAddress());
return VMObjectFactory.newObject(U1Array.class, addr);
}
public long getConstMethodSize() {
return constMethodSize.getValue(this);
}

@ -27,6 +27,7 @@ package sun.jvm.hotspot.oops;
import java.io.PrintStream;
import sun.jvm.hotspot.utilities.Observable;
import sun.jvm.hotspot.utilities.Observer;
import sun.jvm.hotspot.utilities.U1Array;
import sun.jvm.hotspot.code.NMethod;
import sun.jvm.hotspot.debugger.Address;
@ -118,6 +119,12 @@ public class Method extends Metadata {
public ConstantPool getConstants() {
return getConstMethod().getConstants();
}
public boolean hasStackMapTable() {
return getConstMethod().hasStackMapTable();
}
public U1Array getStackMapData() {
return getConstMethod().getStackMapData();
}
public MethodData getMethodData() {
Address addr = methodData.getValue(getAddress());
return VMObjectFactory.newObject(MethodData.class, addr);

@ -57,6 +57,7 @@ public class ClassWriter implements /* imports */ ClassConstants
protected short _constantValueIndex;
protected short _codeIndex;
protected short _exceptionsIndex;
protected short _stackMapTableIndex;
protected short _lineNumberTableIndex;
protected short _localVariableTableIndex;
protected short _signatureIndex;
@ -168,6 +169,11 @@ public class ClassWriter implements /* imports */ ClassConstants
// Short deprecatedIndex = (Short) utf8ToIndex.get("Deprecated");
// Code attributes
Short stackMapTableIndex = utf8ToIndex.get("StackMapTable");
_stackMapTableIndex = (stackMapTableIndex != null) ?
stackMapTableIndex.shortValue() : 0;
if (DEBUG) debugMessage("StackMapTable index = " + _stackMapTableIndex);
Short lineNumberTableIndex = utf8ToIndex.get("LineNumberTable");
_lineNumberTableIndex = (lineNumberTableIndex != null)?
lineNumberTableIndex.shortValue() : 0;
@ -515,6 +521,27 @@ public class ClassWriter implements /* imports */ ClassConstants
2 /* catch_type */);
}
boolean hasStackMapTable = m.hasStackMapTable();
U1Array stackMapData = null;
int stackMapAttrLen = 0;
if (hasStackMapTable) {
if (DEBUG) debugMessage("\tmethod has stack map table");
stackMapData = m.getStackMapData();
if (DEBUG) debugMessage("\t\tstack map table length = " + stackMapData.length());
stackMapAttrLen = stackMapData.length();
codeSize += 2 /* stack map table attr index */ +
4 /* stack map table attr length */ +
stackMapAttrLen;
if (DEBUG) debugMessage("\t\tstack map table attr size = " +
stackMapAttrLen);
codeAttrCount++;
}
boolean hasLineNumberTable = m.hasLineNumberTable();
LineNumberTableElement[] lineNumberTable = null;
int lineNumberAttrLen = 0;
@ -601,6 +628,17 @@ public class ClassWriter implements /* imports */ ClassConstants
dos.writeShort(codeAttrCount);
if (DEBUG) debugMessage("\tcode attribute count = " + codeAttrCount);
// write StackMapTable, if available
if (hasStackMapTable) {
writeIndex(_stackMapTableIndex);
dos.writeInt(stackMapAttrLen);
// We write bytes directly as stackMapData is
// raw data (#entries + entries)
for (int i = 0; i < stackMapData.length(); i++) {
dos.writeByte(stackMapData.at(i));
}
}
// write LineNumberTable, if available.
if (hasLineNumberTable) {
writeIndex(_lineNumberTableIndex);

@ -86,6 +86,10 @@ public class ClhsdbDumpclass {
System.err.println(out.getStderr());
out.shouldHaveExitValue(0);
out.shouldMatch("public class " + APP_DOT_CLASSNAME);
// StackMapTable might not be generated for a class
// containing only methods with sequential control flows.
// But the class used here (LingeredApp) is not such a case.
out.shouldContain("StackMapTable:");
out.shouldNotContain("Error:");
} catch (SkippedException se) {
throw se;