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 @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.writeIndex(buf.constantPool().utf8Entry(name));
buf.writeInt(0); int lengthIndex = buf.skip(4);
int start = buf.size();
writeBody(buf, attr); writeBody(buf, attr);
int written = buf.size() - start; int written = buf.size() - lengthIndex - 4;
buf.patchInt(start - 4, 4, written); buf.patchInt(lengthIndex, written);
} }
@Override @Override

View File

@ -1,6 +1,5 @@
/* /*
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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; 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 @Override
public void writeIntBytes(int intSize, long intValue) { public void writeIntBytes(int intSize, long intValue) {
reserveSpace(intSize); 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 @Override
public void reserveSpace(int freeBytes) { public void reserveSpace(int freeBytes) {
int minCapacity = offset + freeBytes; int minCapacity = offset + freeBytes;

View File

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

View File

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

View File

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

View File

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