From 9ebc2ecbf613da3bcee1dd5e8920a26d5f6d6df7 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 6 Sep 2024 13:38:22 +0000 Subject: [PATCH] 8339317: Optimize ClassFile writeBuffer Reviewed-by: redestad, liach --- .../impl/AbstractAttributeMapper.java | 10 +++---- .../classfile/impl/AbstractPoolEntry.java | 1 - .../classfile/impl/BufWriterImpl.java | 26 +++++++++++++++++++ .../classfile/impl/DirectClassBuilder.java | 2 +- .../classfile/impl/DirectCodeBuilder.java | 26 +++++++++++-------- .../classfile/impl/SplitConstantPool.java | 4 +-- .../classfile/impl/UnboundAttribute.java | 7 +++-- 7 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java index 8be167cd119..50c0bdc2a9f 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractAttributeMapper.java @@ -62,13 +62,13 @@ public sealed abstract class AbstractAttributeMapper> } @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 diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java index 9f9fcd8d91a..450f6ae1c8c 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java @@ -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 diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java index 2307af79dee..15d3c8f5b34 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java @@ -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; diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java index 0d61895fe9f..59b9c4f70b4 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java @@ -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 diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java index 1b950f28d00..be8765d4d45 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java @@ -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() { + 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); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java index 777da61c49d..4f48c8b731d 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java @@ -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 a diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java b/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java index 5ee3759bba3..3119cfa0f49 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/UnboundAttribute.java @@ -849,11 +849,10 @@ public abstract sealed class UnboundAttribute> @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); } }