From 2e0554a69548dae6e8ce9eec48c82e08dd3c1ffa Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Wed, 25 Sep 2024 02:35:41 +0000 Subject: [PATCH] 8340710: Optimize DirectClassBuilder::build Reviewed-by: liach --- .../classfile/impl/BufWriterImpl.java | 19 +++++++++++++++- .../classfile/impl/DirectClassBuilder.java | 22 +++++++++---------- .../classfile/impl/DirectCodeBuilder.java | 7 ++++++ .../jdk/internal/classfile/impl/Util.java | 17 +++++++++----- 4 files changed, 46 insertions(+), 19 deletions(-) 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 15d3c8f5b34..4cc6c205fe4 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 @@ -36,6 +36,7 @@ import java.lang.classfile.constantpool.PoolEntry; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.vm.annotation.ForceInline; public final class BufWriterImpl implements BufWriter { private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); @@ -99,6 +100,7 @@ public final class BufWriterImpl implements BufWriter { elems[offset++] = (byte) x; } + @ForceInline @Override public void writeU2(int x) { reserveSpace(2); @@ -283,14 +285,19 @@ public final class BufWriterImpl implements BufWriter { // writeIndex methods ensure that any CP info written // is relative to the correct constant pool + @ForceInline @Override public void writeIndex(PoolEntry entry) { int idx = AbstractPoolEntry.maybeClone(constantPool, entry).index(); if (idx < 1 || idx > Character.MAX_VALUE) - throw new IllegalArgumentException(idx + " is not a valid index. Entry: " + entry); + throw invalidIndex(idx, entry); writeU2(idx); } + static IllegalArgumentException invalidIndex(int idx, PoolEntry entry) { + return new IllegalArgumentException(idx + " is not a valid index. Entry: " + entry); + } + @Override public void writeIndexOrZero(PoolEntry entry) { if (entry == null || entry.index() == 0) @@ -298,4 +305,14 @@ public final class BufWriterImpl implements BufWriter { else writeIndex(entry); } + + /** + * Join head and tail into an exact-size buffer + */ + static byte[] join(BufWriterImpl head, BufWriterImpl tail) { + byte[] result = new byte[head.size() + tail.size()]; + head.copyTo(result, 0); + tail.copyTo(result, head.size()); + return result; + } } 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 6901ae7e24c..e92494e6992 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 @@ -175,14 +175,16 @@ public final class DirectClassBuilder // BSM writers until everything else is written. // Do this early because it might trigger CP activity + var constantPool = this.constantPool; ClassEntry superclass = superclassEntry; if (superclass != null) superclass = AbstractPoolEntry.maybeClone(constantPool, superclass); else if ((flags & ClassFile.ACC_MODULE) == 0 && !"java/lang/Object".equals(thisClassEntry.asInternalName())) superclass = constantPool.classEntry(ConstantDescs.CD_Object); - List ies = new ArrayList<>(interfaceEntries.size()); - for (ClassEntry ce : interfaceEntries) - ies.add(AbstractPoolEntry.maybeClone(constantPool, ce)); + int interfaceEntriesSize = interfaceEntries.size(); + List ies = new ArrayList<>(interfaceEntriesSize); + for (int i = 0; i < interfaceEntriesSize; i++) + ies.add(AbstractPoolEntry.maybeClone(constantPool, interfaceEntries.get(i))); // We maintain two writers, and then we join them at the end int size = sizeHint == 0 ? 256 : sizeHint; @@ -197,16 +199,15 @@ public final class DirectClassBuilder attributes.writeTo(tail); // Now we have to append the BSM, if there is one - boolean written = constantPool.writeBootstrapMethods(tail); - if (written) { + if (constantPool.writeBootstrapMethods(tail)) { // Update attributes count tail.patchU2(attributesOffset, attributes.size() + 1); } // Now we can make the head - head.writeInt(ClassFile.MAGIC_NUMBER); - head.writeU2(minorVersion); - head.writeU2(majorVersion); + head.writeLong((((long) ClassFile.MAGIC_NUMBER) << 32) + | ((minorVersion & 0xFFFFL) << 16) + | (majorVersion & 0xFFFFL)); constantPool.writeTo(head); head.writeU2(flags); head.writeIndex(thisClassEntry); @@ -214,9 +215,6 @@ public final class DirectClassBuilder Util.writeListIndices(head, ies); // Join head and tail into an exact-size buffer - byte[] result = new byte[head.size() + tail.size()]; - head.copyTo(result, 0); - tail.copyTo(result, head.size()); - return result; + return BufWriterImpl.join(head, tail); } } 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 a9be0695911..fd7a8e55bf8 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 @@ -190,6 +190,13 @@ public final class DirectCodeBuilder int pos = buf.size(); int handlersSize = handlers.size(); buf.writeU2(handlersSize); + if (handlersSize > 0) { + writeExceptionHandlers(buf, pos); + } + } + + private void writeExceptionHandlers(BufWriterImpl buf, int pos) { + int handlersSize = handlers.size(); for (AbstractPseudoInstruction.ExceptionCatchImpl h : handlers) { int startPc = labelToBci(h.tryStart()); int endPc = labelToBci(h.tryEnd()); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java index 80d908f6ce7..e1e3f6fb3d2 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java @@ -50,6 +50,7 @@ import java.lang.classfile.constantpool.NameAndTypeEntry; import java.lang.constant.ModuleDesc; import java.lang.reflect.AccessFlag; import jdk.internal.access.SharedSecrets; +import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; import static java.lang.classfile.ClassFile.ACC_STATIC; @@ -249,17 +250,21 @@ public class Util { } } + @ForceInline public static void writeAttributes(BufWriterImpl buf, List> list) { - buf.writeU2(list.size()); - for (var e : list) { - writeAttribute(buf, e); + int size = list.size(); + buf.writeU2(size); + for (int i = 0; i < size; i++) { + writeAttribute(buf, list.get(i)); } } + @ForceInline static void writeList(BufWriterImpl buf, List list) { - buf.writeU2(list.size()); - for (var e : list) { - e.writeTo(buf); + int size = list.size(); + buf.writeU2(size); + for (int i = 0; i < size; i++) { + list.get(i).writeTo(buf); } }