8339317: Optimize ClassFile writeBuffer
Reviewed-by: redestad, liach
This commit is contained in:
parent
d2b36f0907
commit
9ebc2ecbf6
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user