8339317: Optimize ClassFile writeBuffer

Reviewed-by: redestad, liach
This commit is contained in:
Shaojin Wen 2024-09-06 13:38:22 +00:00 committed by Chen Liang
parent d2b36f0907
commit 9ebc2ecbf6
7 changed files with 52 additions and 24 deletions

View File

@ -62,13 +62,13 @@ public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
}
@Override
public final void writeAttribute(BufWriter buf, T attr) {
public final void writeAttribute(BufWriter writer, T attr) {
BufWriterImpl buf = (BufWriterImpl) writer;
buf.writeIndex(buf.constantPool().utf8Entry(name));
buf.writeInt(0);
int start = buf.size();
int lengthIndex = buf.skip(4);
writeBody(buf, attr);
int written = buf.size() - start;
buf.patchInt(start - 4, 4, written);
int written = buf.size() - lengthIndex - 4;
buf.patchInt(lengthIndex, written);
}
@Override

View File

@ -1,6 +1,5 @@
/*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it

View File

@ -217,6 +217,20 @@ public final class BufWriterImpl implements BufWriter {
this.offset = prevOffset;
}
public void patchU2(int offset, int x) {
byte[] elems = this.elems;
elems[offset ] = (byte) (x >> 8);
elems[offset + 1] = (byte) x;
}
public void patchInt(int offset, int x) {
byte[] elems = this.elems;
elems[offset ] = (byte) (x >> 24);
elems[offset + 1] = (byte) (x >> 16);
elems[offset + 2] = (byte) (x >> 8);
elems[offset + 3] = (byte) x;
}
@Override
public void writeIntBytes(int intSize, long intValue) {
reserveSpace(intSize);
@ -225,6 +239,18 @@ public final class BufWriterImpl implements BufWriter {
}
}
/**
* Skip a few bytes in the output buffer. The skipped area has undefined value.
* @param bytes number of bytes to skip
* @return the index, for later patching
*/
public int skip(int bytes) {
int now = offset;
reserveSpace(bytes);
offset += bytes;
return now;
}
@Override
public void reserveSpace(int freeBytes) {
int minCapacity = offset + freeBytes;

View File

@ -192,7 +192,7 @@ public final class DirectClassBuilder
boolean written = constantPool.writeBootstrapMethods(tail);
if (written) {
// Update attributes count
tail.patchInt(attributesOffset, 2, attributes.size() + 1);
tail.patchU2(attributesOffset, attributes.size() + 1);
}
// Now we can make the head

View File

@ -209,7 +209,7 @@ public final class DirectCodeBuilder
}
}
if (handlersSize < handlers.size())
buf.patchInt(pos, 2, handlersSize);
buf.patchU2(pos, handlersSize);
}
private void buildContent() {
@ -246,7 +246,7 @@ public final class DirectCodeBuilder
}
}
if (crSize < characterRanges.size())
b.patchInt(pos, 2, crSize);
b.patchU2(pos, crSize);
}
};
attributes.withAttribute(a);
@ -269,7 +269,7 @@ public final class DirectCodeBuilder
}
}
if (lvSize < localVariables.size())
b.patchInt(pos, 2, lvSize);
b.patchU2(pos, lvSize);
}
};
attributes.withAttribute(a);
@ -292,7 +292,7 @@ public final class DirectCodeBuilder
}
}
if (lvtSize < localVariableTypes.size())
b.patchInt(pos, 2, lvtSize);
b.patchU2(pos, lvtSize);
}
};
attributes.withAttribute(a);
@ -455,8 +455,7 @@ public final class DirectCodeBuilder
private void writeLabelOffset(int nBytes, int instructionPc, Label label) {
int targetBci = labelToBci(label);
if (targetBci == -1) {
int pc = curPc();
bytecodesBufWriter.writeIntBytes(nBytes, 0);
int pc = bytecodesBufWriter.skip(nBytes);
if (deferredLabels == null)
deferredLabels = new ArrayList<>();
deferredLabels.add(new DeferredLabel(pc, nBytes, instructionPc, label));
@ -472,8 +471,13 @@ public final class DirectCodeBuilder
if (deferredLabels != null) {
for (DeferredLabel dl : deferredLabels) {
int branchOffset = labelToBci(dl.label) - dl.instructionPc;
if (dl.size == 2 && (short)branchOffset != branchOffset) throw new LabelOverflowException();
bytecodesBufWriter.patchInt(dl.labelPc, dl.size, branchOffset);
if (dl.size == 2) {
if ((short)branchOffset != branchOffset) throw new LabelOverflowException();
bytecodesBufWriter.patchU2(dl.labelPc, branchOffset);
} else {
assert dl.size == 4;
bytecodesBufWriter.patchInt(dl.labelPc, branchOffset);
}
}
}
}
@ -543,11 +547,11 @@ public final class DirectCodeBuilder
writeBytecode(LOOKUPSWITCH);
int pad = 4 - (curPc() % 4);
if (pad != 4)
bytecodesBufWriter.writeIntBytes(pad, 0);
bytecodesBufWriter.skip(pad); // padding content can be anything
writeLabelOffset(4, instructionPc, defaultTarget);
bytecodesBufWriter.writeInt(cases.size());
cases = new ArrayList<>(cases);
cases.sort(new Comparator<SwitchCase>() {
cases.sort(new Comparator<>() {
@Override
public int compare(SwitchCase c1, SwitchCase c2) {
return Integer.compare(c1.caseValue(), c2.caseValue());
@ -564,7 +568,7 @@ public final class DirectCodeBuilder
writeBytecode(TABLESWITCH);
int pad = 4 - (curPc() % 4);
if (pad != 4)
bytecodesBufWriter.writeIntBytes(pad, 0);
bytecodesBufWriter.skip(pad); // padding content can be anything
writeLabelOffset(4, instructionPc, defaultTarget);
bytecodesBufWriter.writeInt(low);
bytecodesBufWriter.writeInt(high);

View File

@ -142,8 +142,8 @@ public final class SplitConstantPool implements ConstantPoolBuilder {
for (int i = parentBsmSize; i < bsmSize; i++)
bootstrapMethodEntry(i).writeTo(buf);
int attrLen = buf.size() - pos;
buf.patchInt(pos + 2, 4, attrLen - 6);
buf.patchInt(pos + 6, 2, bsmSize);
buf.patchInt(pos + 2, attrLen - 6);
buf.patchU2(pos + 6, bsmSize);
}
else {
UnboundAttribute<BootstrapMethodsAttribute> a

View File

@ -849,11 +849,10 @@ public abstract sealed class UnboundAttribute<T extends Attribute<T>>
@Override
public void writeTo(BufWriterImpl b) {
b.writeIndex(b.constantPool().utf8Entry(mapper.name()));
b.writeInt(0);
int start = b.size();
int lengthIndex = b.skip(4);
writeBody(b);
int written = b.size() - start;
b.patchInt(start - 4, 4, written);
int written = b.size() - lengthIndex - 4;
b.patchInt(lengthIndex, written);
}
}