Skip to content

Commit 047c2d7

Browse files
wenshaocl4esliach
committedOct 9, 2024
8341141: Optimize DirectCodeBuilder
Co-authored-by: Claes Redestad <redestad@openjdk.org> Co-authored-by: Chen Liang <liach@openjdk.org> Reviewed-by: liach, redestad
1 parent d636e0d commit 047c2d7

19 files changed

+881
-413
lines changed
 

‎src/java.base/share/classes/jdk/internal/classfile/impl/AbstractInstruction.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,12 @@ public TypeKind typeKind() {
801801

802802
@Override
803803
public void writeTo(DirectCodeBuilder writer) {
804-
writer.writeLocalVar(op, slot);
804+
var op = this.op;
805+
if (op.sizeIfFixed() == 1) {
806+
writer.writeBytecode(op);
807+
} else {
808+
writer.writeLocalVar(op, slot);
809+
}
805810
}
806811

807812
@Override
@@ -832,7 +837,12 @@ public TypeKind typeKind() {
832837

833838
@Override
834839
public void writeTo(DirectCodeBuilder writer) {
835-
writer.writeLocalVar(op, slot);
840+
var op = this.op;
841+
if (op.sizeIfFixed() == 1) {
842+
writer.writeBytecode(op);
843+
} else {
844+
writer.writeLocalVar(op, slot);
845+
}
836846
}
837847

838848
@Override

‎src/java.base/share/classes/jdk/internal/classfile/impl/AbstractPoolEntry.java

+6-14
Original file line numberDiff line numberDiff line change
@@ -461,14 +461,13 @@ public boolean equalsString(String s) {
461461

462462
@Override
463463
void writeTo(BufWriterImpl pool) {
464-
pool.writeU1(TAG_UTF8);
465464
if (rawBytes != null) {
466-
pool.writeU2(rawLen);
465+
pool.writeU1U2(TAG_UTF8, rawLen);
467466
pool.writeBytes(rawBytes, offset, rawLen);
468467
}
469468
else {
470469
// state == STRING and no raw bytes
471-
pool.writeUTF(stringValue);
470+
pool.writeUtfEntry(stringValue);
472471
}
473472
}
474473

@@ -502,8 +501,7 @@ public T ref1() {
502501
}
503502

504503
void writeTo(BufWriterImpl pool) {
505-
pool.writeU1(tag());
506-
pool.writeU2(ref1.index());
504+
pool.writeU1U2(tag(), ref1.index());
507505
}
508506

509507
@Override
@@ -532,9 +530,7 @@ public U ref2() {
532530
}
533531

534532
void writeTo(BufWriterImpl pool) {
535-
pool.writeU1(tag());
536-
pool.writeU2(ref1.index());
537-
pool.writeU2(ref2.index());
533+
pool.writeU1U2U2(tag(), ref1.index(), ref2.index());
538534
}
539535

540536
@Override
@@ -864,9 +860,7 @@ public NameAndTypeEntryImpl nameAndType() {
864860
}
865861

866862
void writeTo(BufWriterImpl pool) {
867-
pool.writeU1(tag());
868-
pool.writeU2(bsmIndex);
869-
pool.writeU2(nameAndType.index());
863+
pool.writeU1U2U2(tag(), bsmIndex, nameAndType.index());
870864
}
871865

872866
@Override
@@ -984,9 +978,7 @@ public DirectMethodHandleDesc asSymbol() {
984978

985979
@Override
986980
void writeTo(BufWriterImpl pool) {
987-
pool.writeU1(TAG_METHOD_HANDLE);
988-
pool.writeU1(refKind);
989-
pool.writeU2(reference.index());
981+
pool.writeU1U1U2(TAG_METHOD_HANDLE, refKind, reference.index());
990982
}
991983

992984
@Override

‎src/java.base/share/classes/jdk/internal/classfile/impl/AnnotationReader.java

+3-7
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,7 @@ public static void writeTypeAnnotation(BufWriterImpl buf, TypeAnnotation ta) {
315315
case TypeAnnotation.TypeParameterTarget tpt -> buf.writeU1(tpt.typeParameterIndex());
316316
case TypeAnnotation.SupertypeTarget st -> buf.writeU2(st.supertypeIndex());
317317
case TypeAnnotation.TypeParameterBoundTarget tpbt -> {
318-
buf.writeU1(tpbt.typeParameterIndex());
319-
buf.writeU1(tpbt.boundIndex());
318+
buf.writeU1U1(tpbt.typeParameterIndex(), tpbt.boundIndex());
320319
}
321320
case TypeAnnotation.EmptyTarget _ -> {
322321
// nothing to write
@@ -327,9 +326,7 @@ public static void writeTypeAnnotation(BufWriterImpl buf, TypeAnnotation ta) {
327326
buf.writeU2(lvt.table().size());
328327
for (var e : lvt.table()) {
329328
int startPc = labelToBci(lr, e.startLabel(), ta);
330-
buf.writeU2(startPc);
331-
buf.writeU2(labelToBci(lr, e.endLabel(), ta) - startPc);
332-
buf.writeU2(e.index());
329+
buf.writeU2U2U2(startPc, labelToBci(lr, e.endLabel(), ta) - startPc, e.index());
333330
}
334331
}
335332
case TypeAnnotation.CatchTarget ct -> buf.writeU2(ct.exceptionTableIndex());
@@ -343,8 +340,7 @@ public static void writeTypeAnnotation(BufWriterImpl buf, TypeAnnotation ta) {
343340
// target_path
344341
buf.writeU1(ta.targetPath().size());
345342
for (TypeAnnotation.TypePathComponent component : ta.targetPath()) {
346-
buf.writeU1(component.typePathKind().tag());
347-
buf.writeU1(component.typeArgumentIndex());
343+
buf.writeU1U1(component.typePathKind().tag(), component.typeArgumentIndex());
348344
}
349345

350346
// annotation data

‎src/java.base/share/classes/jdk/internal/classfile/impl/AttributeHolder.java

+35-16
Original file line numberDiff line numberDiff line change
@@ -24,51 +24,70 @@
2424
*/
2525
package jdk.internal.classfile.impl;
2626

27-
import java.util.ArrayList;
28-
import java.util.List;
27+
import java.util.Arrays;
2928

3029
import java.lang.classfile.Attribute;
3130
import java.lang.classfile.AttributeMapper;
3231

3332
public class AttributeHolder {
34-
private final List<Attribute<?>> attributes = new ArrayList<>();
33+
private static final Attribute<?>[] EMPTY_ATTRIBUTE_ARRAY = {};
34+
private int attributesCount = 0;
35+
private Attribute<?>[] attributes = EMPTY_ATTRIBUTE_ARRAY;
3536

3637
public <A extends Attribute<A>> void withAttribute(Attribute<?> a) {
3738
if (a == null)
3839
return;
3940

4041
@SuppressWarnings("unchecked")
4142
AttributeMapper<A> am = (AttributeMapper<A>) a.attributeMapper();
42-
if (!am.allowMultiple() && isPresent(am)) {
43-
remove(am);
43+
int attributesCount = this.attributesCount;
44+
var attributes = this.attributes;
45+
if (!am.allowMultiple()) {
46+
// remove if
47+
for (int i = attributesCount - 1; i >= 0; i--) {
48+
if (attributes[i].attributeMapper() == am) {
49+
attributesCount--;
50+
System.arraycopy(attributes, i + 1, attributes, i, attributesCount - i);
51+
}
52+
}
4453
}
45-
attributes.add(a);
54+
55+
// add attribute
56+
if (attributesCount >= attributes.length) {
57+
int newCapacity = attributesCount + 4;
58+
this.attributes = attributes = Arrays.copyOf(attributes, newCapacity);
59+
}
60+
attributes[attributesCount] = a;
61+
this.attributesCount = attributesCount + 1;
4662
}
4763

4864
public int size() {
49-
return attributes.size();
65+
return attributesCount;
5066
}
5167

5268
public void writeTo(BufWriterImpl buf) {
53-
Util.writeAttributes(buf, attributes);
69+
int attributesCount = this.attributesCount;
70+
buf.writeU2(attributesCount);
71+
for (int i = 0; i < attributesCount; i++) {
72+
Util.writeAttribute(buf, attributes[i]);
73+
}
5474
}
5575

5676
@SuppressWarnings("unchecked")
5777
<A extends Attribute<A>> A get(AttributeMapper<A> am) {
58-
for (Attribute<?> a : attributes)
78+
for (int i = 0; i < attributesCount; i++) {
79+
Attribute<?> a = attributes[i];
5980
if (a.attributeMapper() == am)
60-
return (A)a;
81+
return (A) a;
82+
}
6183
return null;
6284
}
6385

6486
boolean isPresent(AttributeMapper<?> am) {
65-
for (Attribute<?> a : attributes)
66-
if (a.attributeMapper() == am)
87+
for (int i = 0; i < attributesCount; i++) {
88+
if (attributes[i].attributeMapper() == am)
6789
return true;
90+
}
6891
return false;
6992
}
70-
71-
private void remove(AttributeMapper<?> am) {
72-
attributes.removeIf(a -> a.attributeMapper() == am);
73-
}
7493
}

‎src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java

+96-9
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import jdk.internal.access.SharedSecrets;
3939
import jdk.internal.vm.annotation.ForceInline;
4040

41+
import static java.lang.classfile.constantpool.PoolEntry.TAG_UTF8;
4142
import static jdk.internal.util.ModifiedUtf.putChar;
4243
import static jdk.internal.util.ModifiedUtf.utfLen;
4344

@@ -114,6 +115,83 @@ public void writeU2(int x) {
114115
this.offset = offset + 2;
115116
}
116117

118+
@ForceInline
119+
public void writeU1U1(int x1, int x2) {
120+
reserveSpace(2);
121+
byte[] elems = this.elems;
122+
int offset = this.offset;
123+
elems[offset ] = (byte) x1;
124+
elems[offset + 1] = (byte) x2;
125+
this.offset = offset + 2;
126+
}
127+
128+
public void writeU1U2(int u1, int u2) {
129+
reserveSpace(3);
130+
byte[] elems = this.elems;
131+
int offset = this.offset;
132+
elems[offset ] = (byte) u1;
133+
elems[offset + 1] = (byte) (u2 >> 8);
134+
elems[offset + 2] = (byte) u2;
135+
this.offset = offset + 3;
136+
}
137+
138+
public void writeU1U1U1(int x1, int x2, int x3) {
139+
reserveSpace(3);
140+
byte[] elems = this.elems;
141+
int offset = this.offset;
142+
elems[offset ] = (byte) x1;
143+
elems[offset + 1] = (byte) x2;
144+
elems[offset + 2] = (byte) x3;
145+
this.offset = offset + 3;
146+
}
147+
148+
public void writeU1U1U2(int x1, int x2, int x3) {
149+
reserveSpace(4);
150+
byte[] elems = this.elems;
151+
int offset = this.offset;
152+
elems[offset ] = (byte) x1;
153+
elems[offset + 1] = (byte) x2;
154+
elems[offset + 2] = (byte) (x3 >> 8);
155+
elems[offset + 3] = (byte) x3;
156+
this.offset = offset + 4;
157+
}
158+
159+
public void writeU1U2U2(int x1, int x2, int x3) {
160+
reserveSpace(5);
161+
byte[] elems = this.elems;
162+
int offset = this.offset;
163+
elems[offset ] = (byte) x1;
164+
elems[offset + 1] = (byte) (x2 >> 8);
165+
elems[offset + 2] = (byte) x2;
166+
elems[offset + 3] = (byte) (x3 >> 8);
167+
elems[offset + 4] = (byte) x3;
168+
this.offset = offset + 5;
169+
}
170+
171+
public void writeU2U2(int x1, int x2) {
172+
reserveSpace(4);
173+
byte[] elems = this.elems;
174+
int offset = this.offset;
175+
elems[offset ] = (byte) (x1 >> 8);
176+
elems[offset + 1] = (byte) x1;
177+
elems[offset + 2] = (byte) (x2 >> 8);
178+
elems[offset + 3] = (byte) x2;
179+
this.offset = offset + 4;
180+
}
181+
182+
public void writeU2U2U2(int x1, int x2, int x3) {
183+
reserveSpace(6);
184+
byte[] elems = this.elems;
185+
int offset = this.offset;
186+
elems[offset ] = (byte) (x1 >> 8);
187+
elems[offset + 1] = (byte) x1;
188+
elems[offset + 2] = (byte) (x2 >> 8);
189+
elems[offset + 3] = (byte) x2;
190+
elems[offset + 4] = (byte) (x3 >> 8);
191+
elems[offset + 5] = (byte) x3;
192+
this.offset = offset + 6;
193+
}
194+
117195
@Override
118196
public void writeInt(int x) {
119197
reserveSpace(4);
@@ -162,21 +240,22 @@ public void writeBytes(BufWriterImpl other) {
162240
}
163241

164242
@SuppressWarnings("deprecation")
165-
void writeUTF(String str) {
243+
void writeUtfEntry(String str) {
166244
int strlen = str.length();
167245
int countNonZeroAscii = JLA.countNonZeroAscii(str);
168246
int utflen = utfLen(str, countNonZeroAscii);
169247
if (utflen > 65535) {
170248
throw new IllegalArgumentException("string too long");
171249
}
172-
reserveSpace(utflen + 2);
250+
reserveSpace(utflen + 3);
173251

174252
int offset = this.offset;
175253
byte[] elems = this.elems;
176254

177-
elems[offset ] = (byte) (utflen >> 8);
178-
elems[offset + 1] = (byte) utflen;
179-
offset += 2;
255+
elems[offset ] = (byte) TAG_UTF8;
256+
elems[offset + 1] = (byte) (utflen >> 8);
257+
elems[offset + 2] = (byte) utflen;
258+
offset += 3;
180259

181260
str.getBytes(0, countNonZeroAscii, elems, offset);
182261
offset += countNonZeroAscii;
@@ -269,13 +348,21 @@ public void copyTo(byte[] array, int bufferOffset) {
269348
// writeIndex methods ensure that any CP info written
270349
// is relative to the correct constant pool
271350

272-
@ForceInline
273-
@Override
274-
public void writeIndex(PoolEntry entry) {
351+
public int cpIndex(PoolEntry entry) {
275352
int idx = AbstractPoolEntry.maybeClone(constantPool, entry).index();
276353
if (idx < 1 || idx > Character.MAX_VALUE)
277354
throw invalidIndex(idx, entry);
278-
writeU2(idx);
355+
return idx;
356+
}
357+
358+
@ForceInline
359+
@Override
360+
public void writeIndex(PoolEntry entry) {
361+
writeU2(cpIndex(entry));
362+
}
363+
364+
public void writeIndex(int bytecode, PoolEntry entry) {
365+
writeU1U2(bytecode, cpIndex(entry));
279366
}
280367

281368
static IllegalArgumentException invalidIndex(int idx, PoolEntry entry) {

‎src/java.base/share/classes/jdk/internal/classfile/impl/BytecodeHelpers.java

+56
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,11 @@ public static Opcode returnOpcode(TypeKind tk) {
264264
};
265265
}
266266

267+
public static int returnBytecode(TypeKind tk) {
268+
int kind = Math.max(0, tk.ordinal() - 4); // BYTE, SHORT, CHAR, BOOLEAN becomes INT
269+
return IRETURN + kind;
270+
}
271+
267272
public static Opcode arrayLoadOpcode(TypeKind tk) {
268273
return switch (tk) {
269274
case BYTE, BOOLEAN -> Opcode.BALOAD;
@@ -278,6 +283,20 @@ public static Opcode arrayLoadOpcode(TypeKind tk) {
278283
};
279284
}
280285

286+
public static int arrayLoadBytecode(TypeKind tk) {
287+
return switch (tk) {
288+
case BYTE, BOOLEAN -> BALOAD;
289+
case SHORT -> SALOAD;
290+
case INT -> IALOAD;
291+
case FLOAT -> FALOAD;
292+
case LONG -> LALOAD;
293+
case DOUBLE -> DALOAD;
294+
case REFERENCE -> AALOAD;
295+
case CHAR -> CALOAD;
296+
case VOID -> throw new IllegalArgumentException("void not an allowable array type");
297+
};
298+
}
299+
281300
public static Opcode arrayStoreOpcode(TypeKind tk) {
282301
return switch (tk) {
283302
case BYTE, BOOLEAN -> Opcode.BASTORE;
@@ -292,6 +311,20 @@ public static Opcode arrayStoreOpcode(TypeKind tk) {
292311
};
293312
}
294313

314+
public static int arrayStoreBytecode(TypeKind tk) {
315+
return switch (tk) {
316+
case BYTE, BOOLEAN -> BASTORE;
317+
case SHORT -> SASTORE;
318+
case INT -> IASTORE;
319+
case FLOAT -> FASTORE;
320+
case LONG -> LASTORE;
321+
case DOUBLE -> DASTORE;
322+
case REFERENCE -> AASTORE;
323+
case CHAR -> CASTORE;
324+
case VOID -> throw new IllegalArgumentException("void not an allowable array type");
325+
};
326+
}
327+
295328
public static Opcode reverseBranchOpcode(Opcode op) {
296329
return switch (op) {
297330
case IFEQ -> Opcode.IFNE;
@@ -314,6 +347,29 @@ public static Opcode reverseBranchOpcode(Opcode op) {
314347
};
315348
}
316349

350+
public static int reverseBranchOpcode(int bytecode) {
351+
return switch (bytecode) {
352+
case IFEQ -> IFNE;
353+
case IFNE -> IFEQ;
354+
case IFLT -> IFGE;
355+
case IFGE -> IFLT;
356+
case IFGT -> IFLE;
357+
case IFLE -> IFGT;
358+
case IF_ICMPEQ -> IF_ICMPNE;
359+
case IF_ICMPNE -> IF_ICMPEQ;
360+
case IF_ICMPLT -> IF_ICMPGE;
361+
case IF_ICMPGE -> IF_ICMPLT;
362+
case IF_ICMPGT -> IF_ICMPLE;
363+
case IF_ICMPLE -> IF_ICMPGT;
364+
case IF_ACMPEQ -> IF_ACMPNE;
365+
case IF_ACMPNE -> IF_ACMPEQ;
366+
case IFNULL -> IFNONNULL;
367+
case IFNONNULL -> IFNULL;
368+
default -> throw new IllegalArgumentException(
369+
String.format("Wrong opcode kind specified; found %d, expected %s", bytecode, Opcode.Kind.BRANCH));
370+
};
371+
}
372+
317373
public static Opcode convertOpcode(TypeKind from, TypeKind to) {
318374
return switch (from) {
319375
case INT ->

‎src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,11 @@ private static boolean checkTag(int tag, Class<?> cls) {
353353

354354
static <T extends PoolEntry> T checkType(PoolEntry e, int index, Class<T> cls) {
355355
if (cls.isInstance(e)) return cls.cast(e);
356-
throw new ConstantPoolException("Not a " + cls.getSimpleName() + " at index: " + index);
356+
throw checkTypeError(index, cls);
357+
}
358+
359+
private static ConstantPoolException checkTypeError(int index, Class<?> cls) {
360+
return new ConstantPoolException("Not a " + cls.getSimpleName() + " at index: " + index);
357361
}
358362

359363
@Override

‎src/java.base/share/classes/jdk/internal/classfile/impl/DirectClassBuilder.java

+33-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +31,7 @@
3031
import java.lang.constant.MethodTypeDesc;
3132
import java.lang.reflect.AccessFlag;
3233
import java.util.ArrayList;
34+
import java.util.Arrays;
3335
import java.util.Collections;
3436
import java.util.List;
3537
import java.util.function.Consumer;
@@ -54,9 +56,13 @@ public final class DirectClassBuilder
5456

5557
/** The value of default class access flags */
5658
static final int DEFAULT_CLASS_FLAGS = ClassFile.ACC_PUBLIC;
59+
static final Util.Writable[] EMPTY_WRITABLE_ARRAY = {};
60+
static final ClassEntry[] EMPTY_CLASS_ENTRY_ARRAY = {};
5761
final ClassEntry thisClassEntry;
58-
private final List<Util.Writable> fields = new ArrayList<>();
59-
private final List<Util.Writable> methods = new ArrayList<>();
62+
private Util.Writable[] fields = EMPTY_WRITABLE_ARRAY;
63+
private Util.Writable[] methods = EMPTY_WRITABLE_ARRAY;
64+
private int fieldsCount = 0;
65+
private int methodsCount = 0;
6066
private ClassEntry superclassEntry;
6167
private List<ClassEntry> interfaceEntries;
6268
private int majorVersion;
@@ -137,12 +143,20 @@ public ClassBuilder transformMethod(MethodModel method, MethodTransform transfor
137143
// internal / for use by elements
138144

139145
ClassBuilder withField(Util.Writable field) {
140-
fields.add(field);
146+
if (fieldsCount >= fields.length) {
147+
int newCapacity = fieldsCount + 8;
148+
this.fields = Arrays.copyOf(fields, newCapacity);
149+
}
150+
fields[fieldsCount++] = field;
141151
return this;
142152
}
143153

144154
ClassBuilder withMethod(Util.Writable method) {
145-
methods.add(method);
155+
if (methodsCount >= methods.length) {
156+
int newCapacity = methodsCount + 8;
157+
this.methods = Arrays.copyOf(methods, newCapacity);
158+
}
159+
methods[methodsCount++] = method;
146160
return this;
147161
}
148162

@@ -184,9 +198,7 @@ public byte[] build() {
184198
else if ((flags & ClassFile.ACC_MODULE) == 0 && !"java/lang/Object".equals(thisClassEntry.asInternalName()))
185199
superclass = constantPool.classEntry(ConstantDescs.CD_Object);
186200
int interfaceEntriesSize = interfaceEntries.size();
187-
List<ClassEntry> ies = new ArrayList<>(interfaceEntriesSize);
188-
for (int i = 0; i < interfaceEntriesSize; i++)
189-
ies.add(AbstractPoolEntry.maybeClone(constantPool, interfaceEntries.get(i)));
201+
ClassEntry[] ies = interfaceEntriesSize == 0 ? EMPTY_CLASS_ENTRY_ARRAY : buildInterfaceEnties(interfaceEntriesSize);
190202

191203
// We maintain two writers, and then we join them at the end
192204
int size = sizeHint == 0 ? 256 : sizeHint;
@@ -195,8 +207,8 @@ else if ((flags & ClassFile.ACC_MODULE) == 0 && !"java/lang/Object".equals(thisC
195207

196208
// The tail consists of fields and methods, and attributes
197209
// This should trigger all the CP/BSM mutation
198-
Util.writeList(tail, fields);
199-
Util.writeList(tail, methods);
210+
Util.writeList(tail, fields, fieldsCount);
211+
Util.writeList(tail, methods, methodsCount);
200212
int attributesOffset = tail.size();
201213
attributes.writeTo(tail);
202214

@@ -211,12 +223,21 @@ else if ((flags & ClassFile.ACC_MODULE) == 0 && !"java/lang/Object".equals(thisC
211223
| ((minorVersion & 0xFFFFL) << 16)
212224
| (majorVersion & 0xFFFFL));
213225
constantPool.writeTo(head);
214-
head.writeU2(flags);
215-
head.writeIndex(thisClassEntry);
226+
head.writeU2U2(flags, head.cpIndex(thisClassEntry));
216227
head.writeIndexOrZero(superclass);
217-
Util.writeListIndices(head, ies);
228+
head.writeU2(interfaceEntriesSize);
229+
for (int i = 0; i < interfaceEntriesSize; i++) {
230+
head.writeIndex(ies[i]);
231+
}
218232

219233
// Join head and tail into an exact-size buffer
220234
return BufWriterImpl.join(head, tail);
221235
}
236+
237+
private ClassEntry[] buildInterfaceEnties(int interfaceEntriesSize) {
238+
var ies = new ClassEntry[interfaceEntriesSize];
239+
for (int i = 0; i < interfaceEntriesSize; i++)
240+
ies[i] = AbstractPoolEntry.maybeClone(constantPool, interfaceEntries.get(i));
241+
return ies;
242+
}
222243
}

‎src/java.base/share/classes/jdk/internal/classfile/impl/DirectCodeBuilder.java

+575-266
Large diffs are not rendered by default.

‎src/java.base/share/classes/jdk/internal/classfile/impl/DirectMethodBuilder.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,7 @@ public DirectMethodBuilder run(Consumer<? super MethodBuilder> handler) {
148148

149149
@Override
150150
public void writeTo(BufWriterImpl buf) {
151-
buf.writeU2(flags);
152-
buf.writeIndex(name);
153-
buf.writeIndex(desc);
151+
buf.writeU2U2U2(flags, buf.cpIndex(name), buf.cpIndex(desc));
154152
attributes.writeTo(buf);
155153
}
156154
}

‎src/java.base/share/classes/jdk/internal/classfile/impl/EntryMap.java

+1
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ public void put(int hash, int index) {
113113
throw new IllegalArgumentException("hash must be nonzero");
114114

115115
int ptr = (hash & mask1) << 1;
116+
var data = this.data;
116117
int k = data[ptr];
117118
if (k == 0) {
118119
data[ptr] = hash;

‎src/java.base/share/classes/jdk/internal/classfile/impl/LabelImpl.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
*/
2525
package jdk.internal.classfile.impl;
2626

27-
import java.util.Objects;
28-
2927
import java.lang.classfile.Label;
3028
import java.lang.classfile.instruction.LabelTarget;
3129

@@ -52,7 +50,7 @@ public final class LabelImpl
5250
private int bci;
5351

5452
public LabelImpl(LabelContext labelContext, int bci) {
55-
this.labelContext = Objects.requireNonNull(labelContext);
53+
this.labelContext = labelContext;
5654
this.bci = bci;
5755
}
5856

‎src/java.base/share/classes/jdk/internal/classfile/impl/SplitConstantPool.java

+16-6
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
import java.lang.classfile.BootstrapMethodEntry;
3535
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
3636
import java.lang.classfile.constantpool.*;
37-
import java.util.Objects;
3837

3938
import jdk.internal.constant.ConstantUtils;
4039

@@ -87,20 +86,27 @@ public int bootstrapMethodCount() {
8786
@Override
8887
public PoolEntry entryByIndex(int index) {
8988
if (index <= 0 || index >= size()) {
90-
throw new ConstantPoolException("Bad CP index: " + index);
89+
throw badCP(index);
9190
}
9291
PoolEntry pe = (index < parentSize)
9392
? parent.entryByIndex(index)
9493
: myEntries[index - parentSize];
9594
if (pe == null) {
96-
throw new ConstantPoolException("Unusable CP index: " + index);
95+
throw unusableCP(index);
9796
}
9897
return pe;
9998
}
10099

100+
private static ConstantPoolException badCP(int index) {
101+
return new ConstantPoolException("Bad CP index: " + index);
102+
}
103+
104+
private static ConstantPoolException unusableCP(int index) {
105+
return new ConstantPoolException("Unusable CP index: " + index);
106+
}
107+
101108
@Override
102109
public <T extends PoolEntry> T entryByIndex(int index, Class<T> cls) {
103-
Objects.requireNonNull(cls);
104110
return ClassReaderImpl.checkType(entryByIndex(index), index, cls);
105111
}
106112

@@ -165,8 +171,10 @@ void writeTo(BufWriterImpl buf) {
165171
}
166172

167173
private EntryMap map() {
174+
int parentSize = this.parentSize;
175+
var map = this.map;
168176
if (map == null) {
169-
map = new EntryMap(Math.max(size, 1024), .75f);
177+
this.map = map = new EntryMap(Math.max(size, 1024), .75f);
170178

171179
// Doing a full scan here yields fall-off-the-cliff performance results,
172180
// especially if we only need a few entries that are already
@@ -203,8 +211,10 @@ private void fullScan() {
203211
}
204212

205213
private EntryMap bsmMap() {
214+
int bsmSize = this.bsmSize;
215+
var bsmMap = this.bsmMap;
206216
if (bsmMap == null) {
207-
bsmMap = new EntryMap(Math.max(bsmSize, 16), .75f);
217+
this.bsmMap = bsmMap = new EntryMap(Math.max(bsmSize, 16), .75f);
208218
for (int i=0; i<parentBsmSize; i++) {
209219
BootstrapMethodEntryImpl bsm = parent.bootstrapMethodEntry(i);
210220
bsmMap.put(bsm.hash, bsm.index);

‎src/java.base/share/classes/jdk/internal/classfile/impl/StackMapDecoder.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public class StackMapDecoder {
4848
private static final int
4949
SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247,
5050
SAME_EXTENDED = 251;
51-
private static final StackMapFrameInfo[] NO_STACK_FRAME_INFOS = new StackMapFrameInfo[0];
51+
private static final StackMapFrameInfo[] NO_STACK_FRAME_INFOS = {};
5252

5353
private final ClassReader classReader;
5454
private final int pos;

‎src/java.base/share/classes/jdk/internal/classfile/impl/StackMapGenerator.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static StackMapGenerator of(DirectCodeBuilder dcb, BufWriterImpl buf) {
163163
private static final int FLAG_THIS_UNINIT = 0x01;
164164
private static final int FRAME_DEFAULT_CAPACITY = 10;
165165
private static final int T_BOOLEAN = 4, T_LONG = 11;
166-
private static final Frame[] EMPTY_FRAME_ARRAY = new Frame[0];
166+
private static final Frame[] EMPTY_FRAME_ARRAY = {};
167167

168168
private static final int ITEM_TOP = 0,
169169
ITEM_INTEGER = 1,
@@ -1219,7 +1219,9 @@ private static boolean equals(Type[] l1, Type[] l2, int commonSize) {
12191219
return Arrays.equals(l1, 0, commonSize, l2, 0, commonSize);
12201220
}
12211221

1222-
void writeTo(BufWriter out, Frame prevFrame, ConstantPoolBuilder cp) {
1222+
void writeTo(BufWriterImpl out, Frame prevFrame, ConstantPoolBuilder cp) {
1223+
int localsSize = this.localsSize;
1224+
int stackSize = this.stackSize;
12231225
int offsetDelta = offset - prevFrame.offset - 1;
12241226
if (stackSize == 0) {
12251227
int commonLocalsSize = localsSize > prevFrame.localsSize ? prevFrame.localsSize : localsSize;
@@ -1228,8 +1230,7 @@ void writeTo(BufWriter out, Frame prevFrame, ConstantPoolBuilder cp) {
12281230
if (diffLocalsSize == 0 && offsetDelta < 64) { //same frame
12291231
out.writeU1(offsetDelta);
12301232
} else { //chop, same extended or append frame
1231-
out.writeU1(251 + diffLocalsSize);
1232-
out.writeU2(offsetDelta);
1233+
out.writeU1U2(251 + diffLocalsSize, offsetDelta);
12331234
for (int i=commonLocalsSize; i<localsSize; i++) locals[i].writeTo(out, cp);
12341235
}
12351236
return;
@@ -1238,15 +1239,13 @@ void writeTo(BufWriter out, Frame prevFrame, ConstantPoolBuilder cp) {
12381239
if (offsetDelta < 64) { //same locals 1 stack item frame
12391240
out.writeU1(64 + offsetDelta);
12401241
} else { //same locals 1 stack item extended frame
1241-
out.writeU1(247);
1242-
out.writeU2(offsetDelta);
1242+
out.writeU1U2(247, offsetDelta);
12431243
}
12441244
stack[0].writeTo(out, cp);
12451245
return;
12461246
}
12471247
//full frame
1248-
out.writeU1(255);
1249-
out.writeU2(offsetDelta);
1248+
out.writeU1U2(255, offsetDelta);
12501249
out.writeU2(localsSize);
12511250
for (int i=0; i<localsSize; i++) locals[i].writeTo(out, cp);
12521251
out.writeU2(stackSize);

‎src/java.base/share/classes/jdk/internal/classfile/impl/Util.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ public static MethodTypeDesc methodTypeSymbol(Utf8Entry utf8) {
232232
}
233233

234234
@SuppressWarnings("unchecked")
235-
private static <T extends Attribute<T>> void writeAttribute(BufWriterImpl writer, Attribute<?> attr) {
235+
public static <T extends Attribute<T>> void writeAttribute(BufWriterImpl writer, Attribute<?> attr) {
236236
if (attr instanceof CustomAttribute<?> ca) {
237237
var mapper = (AttributeMapper<T>) ca.attributeMapper();
238238
mapper.writeAttribute(writer, (T) ca);
@@ -252,11 +252,10 @@ public static void writeAttributes(BufWriterImpl buf, List<? extends Attribute<?
252252
}
253253

254254
@ForceInline
255-
static void writeList(BufWriterImpl buf, List<Writable> list) {
256-
int size = list.size();
255+
static void writeList(BufWriterImpl buf, Writable[] array, int size) {
257256
buf.writeU2(size);
258257
for (int i = 0; i < size; i++) {
259-
list.get(i).writeTo(buf);
258+
array[i].writeTo(buf);
260259
}
261260
}
262261

@@ -401,6 +400,7 @@ public static int pow31(int k) {
401400
0x54fbc001, 0xb9f78001, 0x2ef34001, 0xb3ef0001, 0x48eac001, 0xede68001, 0xa2e24001,
402401
0x67de0001, 0xcfbc0001, 0x379a0001, 0x9f780001, 0x07560001, 0x6f340001, 0xd7120001,
403402
0x3ef00001, 0x7de00001, 0xbcd00001, 0xfbc00001, 0x3ab00001, 0x79a00001, 0xb8900001,
403+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
404404
};
405405

406406
static int powersIndex(int digit, int index) {
@@ -411,6 +411,6 @@ static int powersIndex(int digit, int index) {
411411
// digit: 0 - 7
412412
// index: 0 - SIGNIFICANT_OCTAL_DIGITS - 1
413413
private static int powerOctal(int digit, int index) {
414-
return digit == 0 ? 1 : powers[powersIndex(digit, index)];
414+
return digit == 0 ? 1 : powers[powersIndex(digit, index) & 0x3F]; // & 0x3F eliminates bound check
415415
}
416416
}

‎src/java.base/share/classes/jdk/internal/constant/MethodTypeDescImpl.java

+24-8
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,31 @@ public String descriptorString() {
287287
if (desc != null)
288288
return desc;
289289

290-
int len = 2 + returnType.descriptorString().length();
291-
for (ClassDesc argType : argTypes) {
292-
len += argType.descriptorString().length();
293-
}
294-
StringBuilder sb = new StringBuilder(len).append('(');
295-
for (ClassDesc argType : argTypes) {
296-
sb.append(argType.descriptorString());
290+
return buildDescriptorString();
291+
}
292+
293+
private String buildDescriptorString() {
294+
var returnType = this.returnType;
295+
var returnTypeDesc = returnType.descriptorString();
296+
var argTypes = this.argTypes;
297+
String desc;
298+
if (argTypes.length == 0) {
299+
// getter
300+
desc = "()".concat(returnTypeDesc);
301+
} else if (argTypes.length == 1 && returnType == ConstantDescs.CD_void) {
302+
// setter
303+
desc = ConstantUtils.concat("(", argTypes[0].descriptorString(), ")V");
304+
} else {
305+
int len = 2 + returnTypeDesc.length();
306+
for (ClassDesc argType : argTypes) {
307+
len += argType.descriptorString().length();
308+
}
309+
StringBuilder sb = new StringBuilder(len).append('(');
310+
for (ClassDesc argType : argTypes) {
311+
sb.append(argType.descriptorString());
312+
}
313+
desc = sb.append(')').append(returnTypeDesc).toString();
297314
}
298-
desc = sb.append(')').append(returnType.descriptorString()).toString();
299315
cachedDescriptorString = desc;
300316
return desc;
301317
}

‎test/jdk/jdk/classfile/UtilTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ void testInternalNameHash(Class<?> type) {
120120
// Ensures the initialization statement of the powers array is filling in the right values
121121
@Test
122122
void testPowersArray() {
123-
int[] powers = new int[7 * UtilAccess.significantOctalDigits()];
123+
int[] powers = new int[64];
124124
for (int i = 1, k = 31; i <= 7; i++, k *= 31) {
125125
int t = powers[UtilAccess.powersIndex(i, 0)] = k;
126126

‎test/micro/org/openjdk/bench/jdk/classfile/Write.java

+3-51
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,9 @@ public byte[] jdkTree() {
141141
cb.withVersion(52, 0);
142142
cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java"))))
143143
.withMethod(INIT_NAME, MTD_void, 0, mb -> mb
144-
.withCode(codeb -> codeb.loadLocal(REFERENCE, 0)
145-
.invoke(INVOKESPECIAL, CD_Object, INIT_NAME, MTD_void, false)
146-
.return_(VOID)
144+
.withCode(codeb -> codeb.aload(0)
145+
.invokespecial(CD_Object, INIT_NAME, MTD_void)
146+
.return_()
147147
)
148148
);
149149
for (int xi = 0; xi < 40; ++xi) {
@@ -180,54 +180,6 @@ public byte[] jdkTree() {
180180
return bytes;
181181
}
182182

183-
@Benchmark
184-
@BenchmarkMode(Mode.Throughput)
185-
public byte[] jdkTreePrimitive() {
186-
187-
byte[] bytes = ClassFile.of().build(CD_MyClass, cb -> {
188-
cb.withFlags(AccessFlag.PUBLIC);
189-
cb.withVersion(52, 0);
190-
cb.with(SourceFileAttribute.of(cb.constantPool().utf8Entry(("MyClass.java"))))
191-
.withMethod(INIT_NAME, MTD_void, 0,
192-
mb -> mb.withCode(codeb -> codeb.loadLocal(REFERENCE, 0)
193-
.invokespecial(CD_Object, INIT_NAME, MTD_void, false)
194-
.return_()
195-
)
196-
);
197-
for (int xi = 0; xi < 40; ++xi) {
198-
cb.withMethod("main" + ((xi == 0) ? "" : "" + xi), MTD_void_StringArray,
199-
ACC_PUBLIC | ACC_STATIC,
200-
mb -> mb.withCode(c0 -> {
201-
java.lang.classfile.Label loopTop = c0.newLabel();
202-
java.lang.classfile.Label loopEnd = c0.newLabel();
203-
int vFac = 1;
204-
int vI = 2;
205-
c0.iconst_1() // 0
206-
.istore(1) // 1
207-
.iconst_1() // 2
208-
.istore(2) // 3
209-
.labelBinding(loopTop)
210-
.iload(2) // 4
211-
.bipush(10) // 5
212-
.if_icmpge(loopEnd) // 6
213-
.iload(1) // 7
214-
.iload(2) // 8
215-
.imul() // 9
216-
.istore(1) // 10
217-
.iinc(2, 1) // 11
218-
.goto_(loopTop) // 12
219-
.labelBinding(loopEnd)
220-
.getstatic(CD_System, "out", CD_PrintStream) // 13
221-
.iload(1)
222-
.invokevirtual(CD_PrintStream, "println", MTD_void_int) // 15
223-
.return_();
224-
}));
225-
}
226-
});
227-
if (writeClassBc) writeClass(bytes, checkFileBc);
228-
return bytes;
229-
}
230-
231183
private void writeClass(byte[] bytes, String fn) {
232184
try {
233185
FileOutputStream out = new FileOutputStream(fn);

0 commit comments

Comments
 (0)
Please sign in to comment.