8341906: Optimize ClassFile writing BufBuffer

Reviewed-by: liach
This commit is contained in:
Shaojin Wen 2024-10-11 00:29:14 +00:00
parent cd4981c292
commit 24eb360147
13 changed files with 119 additions and 111 deletions

View File

@ -140,14 +140,13 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, CharacterRangeTableAttribute attr) {
protected void writeBody(BufWriter bufWriter, CharacterRangeTableAttribute attr) {
List<CharacterRangeInfo> ranges = attr.characterRangeTable();
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2(ranges.size());
for (CharacterRangeInfo info : ranges) {
buf.writeU2(info.startPc());
buf.writeU2(info.endPc());
buf.writeInt(info.characterRangeStart());
buf.writeInt(info.characterRangeEnd());
buf.writeU2U2(info.startPc(), info.endPc());
buf.writeIntInt(info.characterRangeStart(), info.characterRangeEnd());
buf.writeU2(info.flags());
}
}
@ -238,9 +237,10 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, EnclosingMethodAttribute attr) {
buf.writeIndex(attr.enclosingClass());
buf.writeIndexOrZero(attr.enclosingMethod().orElse(null));
protected void writeBody(BufWriter bufWriter, EnclosingMethodAttribute attr) {
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2U2(buf.cpIndex(attr.enclosingClass()),
buf.cpIndexOrZero(attr.enclosingMethod().orElse(null)));
}
}
@ -275,13 +275,14 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, InnerClassesAttribute attr) {
protected void writeBody(BufWriter bufWriter, InnerClassesAttribute attr) {
List<InnerClassInfo> classes = attr.classes();
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2(classes.size());
for (InnerClassInfo ic : classes) {
buf.writeIndex(ic.innerClass());
buf.writeIndexOrZero(ic.outerClass().orElse(null));
buf.writeIndexOrZero(ic.innerName().orElse(null));
buf.writeU2U2U2(buf.cpIndex(ic.innerClass()),
buf.cpIndexOrZero(ic.outerClass().orElse(null)),
buf.cpIndexOrZero(ic.innerName().orElse(null)));
buf.writeU2(ic.flagsMask());
}
}
@ -300,12 +301,12 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, LineNumberTableAttribute attr) {
protected void writeBody(BufWriter bufWriter, LineNumberTableAttribute attr) {
List<LineNumberInfo> lines = attr.lineNumbers();
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2(lines.size());
for (LineNumberInfo line : lines) {
buf.writeU2(line.startPc());
buf.writeU2(line.lineNumber());
buf.writeU2U2(line.startPc(), line.lineNumber());
}
}
}
@ -323,15 +324,13 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, LocalVariableTableAttribute attr) {
protected void writeBody(BufWriter bufWriter, LocalVariableTableAttribute attr) {
List<LocalVariableInfo> infos = attr.localVariables();
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2(infos.size());
for (LocalVariableInfo info : infos) {
buf.writeU2(info.startPc());
buf.writeU2(info.length());
buf.writeIndex(info.name());
buf.writeIndex(info.type());
buf.writeU2(info.slot());
buf.writeU2U2(info.startPc(), info.length());
buf.writeU2U2U2(buf.cpIndex(info.name()), buf.cpIndex(info.type()), info.slot());
}
}
}
@ -349,15 +348,13 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, LocalVariableTypeTableAttribute attr) {
protected void writeBody(BufWriter bufWriter, LocalVariableTypeTableAttribute attr) {
List<LocalVariableTypeInfo> infos = attr.localVariableTypes();
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2(infos.size());
for (LocalVariableTypeInfo info : infos) {
buf.writeU2(info.startPc());
buf.writeU2(info.length());
buf.writeIndex(info.name());
buf.writeIndex(info.signature());
buf.writeU2(info.slot());
buf.writeU2U2(info.startPc(), info.length());
buf.writeU2U2U2(buf.cpIndex(info.name()), buf.cpIndex(info.signature()), info.slot());
}
}
}
@ -375,12 +372,13 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, MethodParametersAttribute attr) {
protected void writeBody(BufWriter bufWriter, MethodParametersAttribute attr) {
List<MethodParameterInfo> parameters = attr.parameters();
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU1(parameters.size());
for (MethodParameterInfo info : parameters) {
buf.writeIndexOrZero(info.name().orElse(null));
buf.writeU2(info.flagsMask());
buf.writeU2U2(buf.cpIndexOrZero(info.name().orElse(null)),
info.flagsMask());
}
}
}
@ -398,26 +396,27 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, ModuleAttribute attr) {
buf.writeIndex(attr.moduleName());
buf.writeU2(attr.moduleFlagsMask());
buf.writeIndexOrZero(attr.moduleVersion().orElse(null));
protected void writeBody(BufWriter bufWriter, ModuleAttribute attr) {
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2U2U2(buf.cpIndex(attr.moduleName()),
attr.moduleFlagsMask(),
buf.cpIndexOrZero(attr.moduleVersion().orElse(null)));
buf.writeU2(attr.requires().size());
for (ModuleRequireInfo require : attr.requires()) {
buf.writeIndex(require.requires());
buf.writeU2(require.requiresFlagsMask());
buf.writeIndexOrZero(require.requiresVersion().orElse(null));
buf.writeU2U2U2(buf.cpIndex(require.requires()),
require.requiresFlagsMask(),
buf.cpIndexOrZero(require.requiresVersion().orElse(null)));
}
buf.writeU2(attr.exports().size());
for (ModuleExportInfo export : attr.exports()) {
buf.writeIndex(export.exportedPackage());
buf.writeU2(export.exportsFlagsMask());
buf.writeU2U2(buf.cpIndex(export.exportedPackage()),
export.exportsFlagsMask());
Util.writeListIndices(buf, export.exportsTo());
}
buf.writeU2(attr.opens().size());
for (ModuleOpenInfo open : attr.opens()) {
buf.writeIndex(open.openedPackage());
buf.writeU2(open.opensFlagsMask());
buf.writeU2U2(buf.cpIndex(open.openedPackage()),
open.opensFlagsMask());
Util.writeListIndices(buf, open.opensTo());
}
Util.writeListIndices(buf, attr.uses());
@ -442,13 +441,13 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, ModuleHashesAttribute attr) {
buf.writeIndex(attr.algorithm());
protected void writeBody(BufWriter bufWriter, ModuleHashesAttribute attr) {
List<ModuleHashInfo> hashes = attr.hashes();
buf.writeU2(hashes.size());
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2U2(buf.cpIndex(attr.algorithm()), hashes.size());
for (ModuleHashInfo hash : hashes) {
buf.writeIndex(hash.moduleName());
buf.writeU2(hash.hash().length);
buf.writeU2U2(buf.cpIndex(hash.moduleName()),
hash.hash().length);
buf.writeBytes(hash.hash());
}
}
@ -593,13 +592,14 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
protected void writeBody(BufWriter buf, RecordAttribute attr) {
protected void writeBody(BufWriter bufWriter, RecordAttribute attr) {
List<RecordComponentInfo> components = attr.components();
BufWriterImpl buf = (BufWriterImpl) bufWriter;
buf.writeU2(components.size());
for (RecordComponentInfo info : components) {
buf.writeIndex(info.name());
buf.writeIndex(info.descriptor());
Util.writeAttributes((BufWriterImpl) buf, info.attributes());
buf.writeU2U2(buf.cpIndex(info.name()),
buf.cpIndex(info.descriptor()));
Util.writeAttributes(buf, info.attributes());
}
}
}

View File

@ -88,15 +88,12 @@ public class AbstractBoundLocalVariable
return false;
}
int length = endBci - startBci;
b.writeU2(startBci);
b.writeU2(length);
b.writeU2U2(startBci, length);
if (b.canWriteDirect(code.constantPool())) {
b.writeU2(nameIndex());
b.writeU2(secondaryIndex());
b.writeU2U2(nameIndex(), secondaryIndex());
}
else {
b.writeIndex(name());
b.writeIndex(secondaryEntry());
b.writeU2U2(b.cpIndex(name()), b.cpIndex(secondaryEntry()));
}
b.writeU2(slot());
return true;

View File

@ -200,11 +200,8 @@ public abstract sealed class AbstractPseudoInstruction
return false;
}
int length = endBci - startBci;
b.writeU2(startBci);
b.writeU2(length);
b.writeIndex(name);
b.writeIndex(descriptor);
b.writeU2(slot());
b.writeU2U2(startBci, length);
b.writeU2U2U2(b.cpIndex(name), b.cpIndex(descriptor), slot());
return true;
}
}

View File

@ -282,9 +282,8 @@ public final class AnnotationReader {
}
public static void writeAnnotation(BufWriterImpl buf, Annotation annotation) {
buf.writeIndex(annotation.className());
var elements = annotation.elements();
buf.writeU2(elements.size());
buf.writeU2U2(buf.cpIndex(annotation.className()), elements.size());
for (var e : elements) {
buf.writeIndex(e.name());
AnnotationReader.writeAnnotationValue(buf, e.value());
@ -332,8 +331,8 @@ public final class AnnotationReader {
case TypeAnnotation.CatchTarget ct -> buf.writeU2(ct.exceptionTableIndex());
case TypeAnnotation.OffsetTarget ot -> buf.writeU2(labelToBci(lr, ot.target(), ta));
case TypeAnnotation.TypeArgumentTarget tat -> {
buf.writeU2(labelToBci(lr, tat.target(), ta));
buf.writeU1(tat.typeArgumentIndex());
buf.writeU2U1(labelToBci(lr, tat.target(), ta),
tat.typeArgumentIndex());
}
}

View File

@ -168,6 +168,16 @@ public final class BufWriterImpl implements BufWriter {
this.offset = offset + 5;
}
public void writeU2U1(int x1, int x2) {
reserveSpace(3);
byte[] elems = this.elems;
int offset = this.offset;
elems[offset ] = (byte) (x1 >> 8);
elems[offset + 1] = (byte) x1;
elems[offset + 2] = (byte) x2;
this.offset = offset + 3;
}
public void writeU2U2(int x1, int x2) {
reserveSpace(4);
byte[] elems = this.elems;
@ -204,6 +214,21 @@ public final class BufWriterImpl implements BufWriter {
this.offset = offset + 4;
}
public void writeIntInt(int x1, int x2) {
reserveSpace(8);
byte[] elems = this.elems;
int offset = this.offset;
elems[offset ] = (byte) (x1 >> 24);
elems[offset + 1] = (byte) (x1 >> 16);
elems[offset + 2] = (byte) (x1 >> 8);
elems[offset + 3] = (byte) x1;
elems[offset + 4] = (byte) (x2 >> 24);
elems[offset + 5] = (byte) (x2 >> 16);
elems[offset + 6] = (byte) (x2 >> 8);
elems[offset + 7] = (byte) x2;
this.offset = offset + 8;
}
@Override
public void writeFloat(float x) {
writeInt(Float.floatToIntBits(x));
@ -355,6 +380,12 @@ public final class BufWriterImpl implements BufWriter {
return idx;
}
public int cpIndexOrZero(PoolEntry entry) {
if (entry == null || entry.index() == 0)
return 0;
return cpIndex(entry);
}
@ForceInline
@Override
public void writeIndex(PoolEntry entry) {
@ -371,10 +402,7 @@ public final class BufWriterImpl implements BufWriter {
@Override
public void writeIndexOrZero(PoolEntry entry) {
if (entry == null || entry.index() == 0)
writeU2(0);
else
writeIndex(entry);
writeU2(cpIndexOrZero(entry));
}
/**

View File

@ -219,12 +219,10 @@ public final class DirectClassBuilder
}
// Now we can make the head
head.writeLong((((long) ClassFile.MAGIC_NUMBER) << 32)
| ((minorVersion & 0xFFFFL) << 16)
| (majorVersion & 0xFFFFL));
head.writeInt(ClassFile.MAGIC_NUMBER);
head.writeU2U2(minorVersion, majorVersion);
constantPool.writeTo(head);
head.writeU2U2(flags, head.cpIndex(thisClassEntry));
head.writeIndexOrZero(superclass);
head.writeU2U2U2(flags, head.cpIndex(thisClassEntry), head.cpIndexOrZero(superclass));
head.writeU2(interfaceEntriesSize);
for (int i = 0; i < interfaceEntriesSize; i++) {
head.writeIndex(ies[i]);

View File

@ -257,8 +257,7 @@ public final class DirectCodeBuilder
}
} else {
b.writeU2U2(start, end - 1);
b.writeInt(cr.characterRangeStart());
b.writeInt(cr.characterRangeEnd());
b.writeIntInt(cr.characterRangeStart(), cr.characterRangeEnd());
b.writeU2(cr.flags());
}
}
@ -640,8 +639,7 @@ public final class DirectCodeBuilder
if (pad != 4)
bytecodesBufWriter.skip(pad); // padding content can be anything
writeLongLabelOffset(instructionPc, defaultTarget);
bytecodesBufWriter.writeInt(low);
bytecodesBufWriter.writeInt(high);
bytecodesBufWriter.writeIntInt(low, high);
var caseMap = new HashMap<Integer, Label>(cases.size());
for (var c : cases) {
caseMap.put(c.caseValue(), c.target());
@ -668,8 +666,7 @@ public final class DirectCodeBuilder
}
public void writeInvokeDynamic(InvokeDynamicEntry ref) {
bytecodesBufWriter.writeIndex(INVOKEDYNAMIC, ref);
bytecodesBufWriter.writeU2(0);
bytecodesBufWriter.writeU1U2U2(INVOKEDYNAMIC, bytecodesBufWriter.cpIndex(ref), 0);
}
public void writeNewObject(ClassEntry type) {

View File

@ -80,9 +80,7 @@ public final class DirectFieldBuilder
@Override
public void writeTo(BufWriterImpl buf) {
buf.writeU2(flags);
buf.writeIndex(name);
buf.writeIndex(desc);
buf.writeU2U2U2(flags, buf.cpIndex(name), buf.cpIndex(desc));
attributes.writeTo(buf);
}
}

View File

@ -84,9 +84,9 @@ public final class FieldImpl
reader.copyBytesTo(buf, startPos, endPos - startPos);
}
else {
buf.writeU2(flags().flagsMask());
buf.writeIndex(fieldName());
buf.writeIndex(fieldType());
buf.writeU2U2U2(flags().flagsMask(),
buf.cpIndex(fieldName()),
buf.cpIndex(fieldType()));
Util.writeAttributes(buf, attributes());
}
}

View File

@ -103,9 +103,9 @@ public final class MethodImpl
reader.copyBytesTo(buf, startPos, endPos - startPos);
}
else {
buf.writeU2(flags().flagsMask());
buf.writeIndex(methodName());
buf.writeIndex(methodType());
buf.writeU2U2U2(flags().flagsMask(),
buf.cpIndex(methodName()),
buf.cpIndex(methodType()));
Util.writeAttributes(buf, attributes());
}
}

View File

@ -135,8 +135,7 @@ public class StackMapDecoder {
if (diffLocalsSize == 0 && offsetDelta < 64) { //same frame
out.writeU1(offsetDelta);
} else { //chop, same extended or append frame
out.writeU1(251 + diffLocalsSize);
out.writeU2(offsetDelta);
out.writeU1U2(251 + diffLocalsSize, offsetDelta);
for (int i=commonLocalsSize; i<fr.locals().size(); i++) writeTypeInfo(out, fr.locals().get(i));
}
return;
@ -145,16 +144,13 @@ public class StackMapDecoder {
if (offsetDelta < 64) { //same locals 1 stack item frame
out.writeU1(64 + offsetDelta);
} else { //same locals 1 stack item extended frame
out.writeU1(247);
out.writeU2(offsetDelta);
out.writeU1U2(247, offsetDelta);
}
writeTypeInfo(out, fr.stack().get(0));
return;
}
//full frame
out.writeU1(255);
out.writeU2(offsetDelta);
out.writeU2(fr.locals().size());
out.writeU1U2U2(255, offsetDelta, fr.locals().size());
for (var l : fr.locals()) writeTypeInfo(out, l);
out.writeU2(fr.stack().size());
for (var s : fr.stack()) writeTypeInfo(out, s);
@ -168,15 +164,15 @@ public class StackMapDecoder {
}
private static void writeTypeInfo(BufWriterImpl bw, VerificationTypeInfo vti) {
bw.writeU1(vti.tag());
switch (vti.tag()) {
int tag = vti.tag();
switch (tag) {
case ITEM_TOP, ITEM_INTEGER, ITEM_FLOAT, ITEM_DOUBLE, ITEM_LONG, ITEM_NULL,
ITEM_UNINITIALIZED_THIS ->
{}
bw.writeU1(tag);
case ITEM_OBJECT ->
bw.writeIndex(((ObjectVerificationTypeInfo)vti).className());
bw.writeU1U2(tag, bw.cpIndex(((ObjectVerificationTypeInfo)vti).className()));
case ITEM_UNINITIALIZED ->
bw.writeU2(bw.labelContext().labelToBci(((UninitializedVerificationTypeInfo)vti).newTarget()));
bw.writeU1U2(tag, bw.labelContext().labelToBci(((UninitializedVerificationTypeInfo)vti).newTarget()));
default -> throw new IllegalArgumentException("Invalid verification type tag: " + vti.tag());
}
}

View File

@ -1432,8 +1432,7 @@ public final class StackMapGenerator {
return;
}
//full frame
out.writeU1U2(255, offsetDelta);
out.writeU2(localsSize);
out.writeU1U2U2(255, offsetDelta, localsSize);
for (int i=0; i<localsSize; i++) locals[i].writeTo(out, cp);
out.writeU2(stackSize);
for (int i=0; i<stackSize; i++) stack[i].writeTo(out, cp);
@ -1600,13 +1599,14 @@ public final class StackMapGenerator {
return Type.TOP_TYPE;
}
void writeTo(BufWriter bw, ConstantPoolBuilder cp) {
bw.writeU1(tag);
void writeTo(BufWriterImpl bw, ConstantPoolBuilder cp) {
switch (tag) {
case ITEM_OBJECT ->
bw.writeU2(cp.classEntry(sym).index());
bw.writeU1U2(tag, cp.classEntry(sym).index());
case ITEM_UNINITIALIZED ->
bw.writeU2(bci);
bw.writeU1U2(tag, bci);
default ->
bw.writeU1(tag);
}
}
}

View File

@ -287,12 +287,10 @@ public class Util {
((DirectMethodBuilder)mb).writeAttribute(new UnboundAttribute.AdHocAttribute<CodeAttribute>(Attributes.code()) {
@Override
public void writeBody(BufWriterImpl b) {
b.writeU2(-1);//max stack
b.writeU2(-1);//max locals
b.writeU2U2(-1, -1);//max stack & locals
b.writeInt(bytecode.length());
b.writeBytes(bytecode.array(), 0, bytecode.length());
b.writeU2(0);//exception handlers
b.writeU2(0);//attributes
b.writeU2U2(0, 0);//exception handlers & attributes
}
}))));
ClassPrinter.toYaml(clm.methods().get(0).code().get(), ClassPrinter.Verbosity.TRACE_ALL, dump);