8309979: BootstrapMethods attribute is missing in class files recreated by SA

Reviewed-by: cjplummer, kevinw
This commit is contained in:
Ashutosh Mehra 2023-06-29 14:16:15 +00:00 committed by Kevin Walls
parent 20f7d05ef2
commit 05c2b6cd47
3 changed files with 91 additions and 9 deletions
src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot

@ -130,7 +130,10 @@ public class ConstantPool extends Metadata implements ClassConstants {
private static int INDY_ARGV_OFFSET;
public U1Array getTags() { return new U1Array(tags.getValue(getAddress())); }
public U2Array getOperands() { return new U2Array(operands.getValue(getAddress())); }
public U2Array getOperands() {
Address addr = operands.getValue(getAddress());
return VMObjectFactory.newObject(U2Array.class, addr);
}
public ConstantPoolCache getCache() {
Address addr = cache.getValue(getAddress());
return VMObjectFactory.newObject(ConstantPoolCache.class, addr);
@ -464,16 +467,50 @@ public class ConstantPool extends Metadata implements ClassConstants {
return res;
}
/** Lookup for multi-operand (InvokeDynamic, Dynamic) entries. */
public short[] getBootstrapSpecifierAt(int i) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(getTagAt(i).isInvokeDynamic() || getTagAt(i).isDynamicConstant(), "Corrupted constant pool");
public int getBootstrapMethodsCount() {
U2Array operands = getOperands();
int count = 0;
if (operands != null) {
// Operands array consists of two parts. First part is an array of 32-bit values which denote
// index of the bootstrap method data in the operands array. Note that elements of operands array are of type short.
// So each element of first part occupies two slots in the array.
// Second part is the bootstrap methods data.
// This layout allows us to get BSM count by getting the index of first BSM and dividing it by 2.
//
// The example below shows layout of operands array with 3 bootstrap methods.
// First part has 3 32-bit values indicating the index of the respective bootstrap methods in
// the operands array.
// The first BSM is at index 6. So the count in this case is 6/2=3.
//
// <-----first part----><-------second part------->
// index: 0 2 4 6 i2 i3
// operands: | 6 | i2 | i3 | bsm1 | bsm2 | bsm3 |
//
count = getOperandOffsetAt(operands, 0) / 2;
}
int bsmSpec = extractLowShortFromInt(this.getIntAt(i));
if (DEBUG) {
System.err.println("ConstantPool.getBootstrapMethodsCount: count = " + count);
}
return count;
}
public int getBootstrapMethodArgsCount(int bsmIndex) {
U2Array operands = getOperands();
if (Assert.ASSERTS_ENABLED) {
Assert.that(operands != null, "Operands is not present");
}
int bsmOffset = getOperandOffsetAt(operands, bsmIndex);
int argc = operands.at(bsmOffset + INDY_ARGC_OFFSET);
if (DEBUG) {
System.err.println("ConstantPool.getBootstrapMethodArgsCount: bsm index = " + bsmIndex + ", args count = " + argc);
}
return argc;
}
public short[] getBootstrapMethodAt(int bsmIndex) {
U2Array operands = getOperands();
if (operands == null) return null; // safety first
int basePos = VM.getVM().buildIntFromShorts(operands.at(bsmSpec * 2 + 0),
operands.at(bsmSpec * 2 + 1));
int basePos = getOperandOffsetAt(operands, bsmIndex);
int argv = basePos + INDY_ARGV_OFFSET;
int argc = operands.at(basePos + INDY_ARGC_OFFSET);
int endPos = argv + argc;
@ -484,6 +521,15 @@ public class ConstantPool extends Metadata implements ClassConstants {
return values;
}
/** Lookup for multi-operand (InvokeDynamic, Dynamic) entries. */
public short[] getBootstrapSpecifierAt(int i) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(getTagAt(i).isInvokeDynamic() || getTagAt(i).isDynamicConstant(), "Corrupted constant pool");
}
int bsmSpec = extractLowShortFromInt(this.getIntAt(i));
return getBootstrapMethodAt(bsmSpec);
}
private static final String[] nameForTag = new String[] {
};
@ -756,4 +802,11 @@ public class ConstantPool extends Metadata implements ClassConstants {
// must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc.
return val & 0xFFFF;
}
// Return the offset of the requested Bootstrap Method in the operands array
private int getOperandOffsetAt(U2Array operands, int bsmIndex) {
return VM.getVM().buildIntFromShorts(operands.at(bsmIndex * 2),
operands.at(bsmIndex * 2 + 1));
}
}

@ -859,7 +859,6 @@ public class InstanceKlass extends Klass {
return VMObjectFactory.newObject(U2Array.class, addr);
}
//----------------------------------------------------------------------
// Internals only below this point
//

@ -61,6 +61,7 @@ public class ClassWriter implements /* imports */ ClassConstants
protected short _lineNumberTableIndex;
protected short _localVariableTableIndex;
protected short _signatureIndex;
protected short _bootstrapMethodsIndex;
protected static int extractHighShortFromInt(int val) {
// must stay in sync with ConstantPool::name_and_type_at_put, method_at_put, etc.
@ -142,6 +143,8 @@ public class ClassWriter implements /* imports */ ClassConstants
_innerClassesIndex = (innerClassesIndex != null)? innerClassesIndex.shortValue() : 0;
if (DEBUG) debugMessage("InnerClasses index = " + _innerClassesIndex);
Short bootstrapMethodsIndex = utf8ToIndex.get("BootstrapMethods");
_bootstrapMethodsIndex = (bootstrapMethodsIndex != null) ? bootstrapMethodsIndex.shortValue() : 0;
// field attributes
Short constantValueIndex = utf8ToIndex.get("ConstantValue");
_constantValueIndex = (constantValueIndex != null)?
@ -723,6 +726,11 @@ public class ClassWriter implements /* imports */ ClassConstants
if (numInnerClasses != 0)
classAttributeCount++;
int bsmCount = klass.getConstants().getBootstrapMethodsCount();
if (bsmCount != 0) {
classAttributeCount++;
}
dos.writeShort(classAttributeCount);
if (DEBUG) debugMessage("class attribute count = " + classAttributeCount);
@ -762,5 +770,27 @@ public class ClassWriter implements /* imports */ ClassConstants
dos.writeShort(innerClasses.at(index));
}
}
// write bootstrap method attribute, if any
if (bsmCount != 0) {
ConstantPool cpool = klass.getConstants();
writeIndex(_bootstrapMethodsIndex);
if (DEBUG) debugMessage("bootstrap methods attribute = " + _bootstrapMethodsIndex);
int attrLen = 2; // num_bootstrap_methods
for (int index = 0; index < bsmCount; index++) {
int bsmArgsCount = cpool.getBootstrapMethodArgsCount(index);
attrLen += 2 // bootstrap_method_ref
+ 2 // num_bootstrap_arguments
+ bsmArgsCount * 2;
}
dos.writeInt(attrLen);
dos.writeShort(bsmCount);
for (int index = 0; index < bsmCount; index++) {
short value[] = cpool.getBootstrapMethodAt(index);
for (int i = 0; i < value.length; i++) {
dos.writeShort(value[i]);
}
}
}
}
}