Skip to content

Commit d7e648b

Browse files
committed
8355775: Improve symbolic sharing in dynamic constant pool entries
Reviewed-by: asotona
1 parent ca5e0b1 commit d7e648b

File tree

6 files changed

+69
-47
lines changed

6 files changed

+69
-47
lines changed

src/java.base/share/classes/java/lang/classfile/CodeBuilder.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -2483,7 +2483,7 @@ default CodeBuilder invokedynamic(DynamicCallSiteDesc ref) {
24832483
var cpArgs = ref.bootstrapArgs();
24842484
List<LoadableConstantEntry> bsArguments = new ArrayList<>(cpArgs.length);
24852485
for (var constantValue : cpArgs) {
2486-
bsArguments.add(BytecodeHelpers.constantEntry(constantPool(), constantValue));
2486+
bsArguments.add(constantPool().loadableConstantEntry(requireNonNull(constantValue)));
24872487
}
24882488
BootstrapMethodEntry bm = constantPool().bsmEntry(bsMethod, bsArguments);
24892489
NameAndTypeEntry nameAndType = constantPool().nameAndTypeEntry(ref.invocationName(), ref.invocationType());
@@ -2941,7 +2941,7 @@ default CodeBuilder lconst_1() {
29412941
* @see ConstantInstruction.LoadConstantInstruction
29422942
*/
29432943
default CodeBuilder ldc(ConstantDesc value) {
2944-
return ldc(BytecodeHelpers.constantEntry(constantPool(), value));
2944+
return ldc(constantPool().loadableConstantEntry(requireNonNull(value)));
29452945
}
29462946

29472947
/**

src/java.base/share/classes/java/lang/classfile/constantpool/ConstantPoolBuilder.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import java.util.List;
3737
import java.util.function.Consumer;
3838

39+
import jdk.internal.classfile.impl.AbstractPoolEntry;
3940
import jdk.internal.classfile.impl.AbstractPoolEntry.ClassEntryImpl;
4041
import jdk.internal.classfile.impl.ClassReaderImpl;
4142
import jdk.internal.classfile.impl.SplitConstantPool;
@@ -385,11 +386,13 @@ default InterfaceMethodRefEntry interfaceMethodRefEntry(ClassDesc owner, String
385386
default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) {
386387
var owner = classEntry(descriptor.owner());
387388
var nat = nameAndTypeEntry(utf8Entry(descriptor.methodName()), utf8Entry(descriptor.lookupDescriptor()));
388-
return methodHandleEntry(descriptor.refKind(), switch (descriptor.kind()) {
389+
var ret = methodHandleEntry(descriptor.refKind(), switch (descriptor.kind()) {
389390
case GETTER, SETTER, STATIC_GETTER, STATIC_SETTER -> fieldRefEntry(owner, nat);
390391
case INTERFACE_STATIC, INTERFACE_VIRTUAL, INTERFACE_SPECIAL -> interfaceMethodRefEntry(owner, nat);
391392
case STATIC, VIRTUAL, SPECIAL, CONSTRUCTOR -> methodRefEntry(owner, nat);
392393
});
394+
((AbstractPoolEntry.MethodHandleEntryImpl) ret).sym = descriptor;
395+
return ret;
393396
}
394397

395398
/**
@@ -414,7 +417,9 @@ default MethodHandleEntry methodHandleEntry(DirectMethodHandleDesc descriptor) {
414417
* @see InvokeDynamicEntry#asSymbol() InvokeDynamicEntry::asSymbol
415418
*/
416419
default InvokeDynamicEntry invokeDynamicEntry(DynamicCallSiteDesc dcsd) {
417-
return invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType()));
420+
var ret = invokeDynamicEntry(bsmEntry((DirectMethodHandleDesc)dcsd.bootstrapMethod(), List.of(dcsd.bootstrapArgs())), nameAndTypeEntry(dcsd.invocationName(), dcsd.invocationType()));
421+
((AbstractPoolEntry.InvokeDynamicEntryImpl) ret).sym = dcsd;
422+
return ret;
418423
}
419424

420425
/**
@@ -440,7 +445,9 @@ InvokeDynamicEntry invokeDynamicEntry(BootstrapMethodEntry bootstrapMethodEntry,
440445
* @see ConstantDynamicEntry#asSymbol() ConstantDynamicEntry::asSymbol
441446
*/
442447
default ConstantDynamicEntry constantDynamicEntry(DynamicConstantDesc<?> dcd) {
443-
return constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType()));
448+
var ret = constantDynamicEntry(bsmEntry(dcd.bootstrapMethod(), List.of(dcd.bootstrapArgs())), nameAndTypeEntry(dcd.constantName(), dcd.constantType()));
449+
((AbstractPoolEntry.ConstantDynamicEntryImpl) ret).sym = dcd;
450+
return ret;
444451
}
445452

446453
/**

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

+49-5
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,13 @@ private ConstantPoolException malformedInput(int px) {
295295

296296
@Override
297297
public Utf8EntryImpl clone(ConstantPoolBuilder cp) {
298-
return (state == State.STRING && rawBytes == null)
298+
var ret = (state == State.STRING && rawBytes == null)
299299
? (Utf8EntryImpl) cp.utf8Entry(stringValue)
300300
: ((SplitConstantPool) cp).maybeCloneUtf8Entry(this);
301+
var mySym = this.typeSym;
302+
if (ret.typeSym == null && mySym != null)
303+
ret.typeSym = mySym;
304+
return ret;
301305
}
302306

303307
@Override
@@ -939,6 +943,8 @@ public static final class InvokeDynamicEntryImpl
939943
extends AbstractDynamicConstantPoolEntry
940944
implements InvokeDynamicEntry {
941945

946+
public @Stable DynamicCallSiteDesc sym;
947+
942948
InvokeDynamicEntryImpl(ConstantPool cpm, int index, int hash, BootstrapMethodEntryImpl bootstrapMethod,
943949
NameAndTypeEntryImpl nameAndType) {
944950
super(cpm, index, hash, bootstrapMethod, nameAndType);
@@ -957,13 +963,27 @@ public int tag() {
957963

958964
@Override
959965
public InvokeDynamicEntry clone(ConstantPoolBuilder cp) {
960-
return cp.invokeDynamicEntry(bootstrap(), nameAndType());
966+
var ret = (InvokeDynamicEntryImpl) cp.invokeDynamicEntry(bootstrap(), nameAndType());
967+
var mySym = this.sym;
968+
if (ret.sym == null && mySym != null)
969+
ret.sym = mySym;
970+
return ret;
971+
}
972+
973+
@Override
974+
public DynamicCallSiteDesc asSymbol() {
975+
var cache = this.sym;
976+
if (cache != null)
977+
return cache;
978+
return this.sym = InvokeDynamicEntry.super.asSymbol();
961979
}
962980
}
963981

964982
public static final class ConstantDynamicEntryImpl extends AbstractDynamicConstantPoolEntry
965983
implements ConstantDynamicEntry {
966984

985+
public @Stable DynamicConstantDesc<?> sym;
986+
967987
ConstantDynamicEntryImpl(ConstantPool cpm, int index, int hash, BootstrapMethodEntryImpl bootstrapMethod,
968988
NameAndTypeEntryImpl nameAndType) {
969989
super(cpm, index, hash, bootstrapMethod, nameAndType);
@@ -982,7 +1002,19 @@ public int tag() {
9821002

9831003
@Override
9841004
public ConstantDynamicEntry clone(ConstantPoolBuilder cp) {
985-
return cp.constantDynamicEntry(bootstrap(), nameAndType());
1005+
var ret = (ConstantDynamicEntryImpl) cp.constantDynamicEntry(bootstrap(), nameAndType());
1006+
var mySym = this.sym;
1007+
if (ret.sym == null && mySym != null)
1008+
ret.sym = mySym;
1009+
return ret;
1010+
}
1011+
1012+
@Override
1013+
public DynamicConstantDesc<?> asSymbol() {
1014+
var cache = this.sym;
1015+
if (cache != null)
1016+
return cache;
1017+
return this.sym = ConstantDynamicEntry.super.asSymbol();
9861018
}
9871019
}
9881020

@@ -991,6 +1023,7 @@ public static final class MethodHandleEntryImpl extends AbstractPoolEntry
9911023

9921024
private final int refKind;
9931025
private final AbstractPoolEntry.AbstractMemberRefEntry reference;
1026+
public @Stable DirectMethodHandleDesc sym;
9941027

9951028
MethodHandleEntryImpl(ConstantPool cpm, int index, int hash, int refKind, AbstractPoolEntry.AbstractMemberRefEntry
9961029
reference) {
@@ -1023,7 +1056,14 @@ public AbstractPoolEntry.AbstractMemberRefEntry reference() {
10231056

10241057
@Override
10251058
public DirectMethodHandleDesc asSymbol() {
1026-
return MethodHandleDesc.of(
1059+
var cache = this.sym;
1060+
if (cache != null)
1061+
return cache;
1062+
return computeSymbol();
1063+
}
1064+
1065+
private DirectMethodHandleDesc computeSymbol() {
1066+
return this.sym = MethodHandleDesc.of(
10271067
DirectMethodHandleDesc.Kind.valueOf(kind(), reference() instanceof InterfaceMethodRefEntry),
10281068
((MemberRefEntry) reference()).owner().asSymbol(),
10291069
((MemberRefEntry) reference()).nameAndType().name().stringValue(),
@@ -1037,7 +1077,11 @@ void writeTo(BufWriterImpl pool) {
10371077

10381078
@Override
10391079
public MethodHandleEntry clone(ConstantPoolBuilder cp) {
1040-
return cp.methodHandleEntry(refKind, reference);
1080+
var ret = (MethodHandleEntryImpl) cp.methodHandleEntry(refKind, reference);
1081+
var mySym = this.sym;
1082+
if (ret.sym == null && mySym != null)
1083+
ret.sym = mySym;
1084+
return ret;
10411085
}
10421086

10431087
@Override

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

+1-35
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -29,12 +29,10 @@
2929
import java.lang.classfile.Opcode;
3030
import java.lang.classfile.TypeKind;
3131
import java.lang.classfile.constantpool.*;
32-
import java.lang.constant.ClassDesc;
3332
import java.lang.constant.ConstantDesc;
3433
import java.lang.constant.ConstantDescs;
3534
import java.lang.constant.DirectMethodHandleDesc;
3635
import java.lang.constant.DynamicConstantDesc;
37-
import java.lang.constant.MethodTypeDesc;
3836
import java.lang.invoke.MethodHandleInfo;
3937
import java.util.ArrayList;
4038
import java.util.List;
@@ -515,38 +513,6 @@ public static Opcode ldcOpcode(LoadableConstantEntry entry) {
515513
: Opcode.LDC;
516514
}
517515

518-
public static LoadableConstantEntry constantEntry(ConstantPoolBuilder constantPool,
519-
ConstantDesc constantValue) {
520-
// this method is invoked during JVM bootstrap - cannot use pattern switch
521-
if (constantValue instanceof Integer value) {
522-
return constantPool.intEntry(value);
523-
}
524-
if (constantValue instanceof String value) {
525-
return constantPool.stringEntry(value);
526-
}
527-
if (constantValue instanceof ClassDesc value && !value.isPrimitive()) {
528-
return constantPool.classEntry(value);
529-
}
530-
if (constantValue instanceof Long value) {
531-
return constantPool.longEntry(value);
532-
}
533-
if (constantValue instanceof Float value) {
534-
return constantPool.floatEntry(value);
535-
}
536-
if (constantValue instanceof Double value) {
537-
return constantPool.doubleEntry(value);
538-
}
539-
if (constantValue instanceof MethodTypeDesc value) {
540-
return constantPool.methodTypeEntry(value);
541-
}
542-
if (constantValue instanceof DirectMethodHandleDesc value) {
543-
return handleDescToHandleInfo(constantPool, value);
544-
} if (constantValue instanceof DynamicConstantDesc<?> value) {
545-
return handleConstantDescToHandleInfo(constantPool, value);
546-
}
547-
throw new UnsupportedOperationException("not yet: " + requireNonNull(constantValue));
548-
}
549-
550516
public static ConstantDesc intrinsicConstantValue(Opcode opcode) {
551517
return switch (opcode) {
552518
case ACONST_NULL -> ConstantDescs.NULL;

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

+5
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.lang.classfile.attribute.BootstrapMethodsAttribute;
3131
import java.lang.classfile.constantpool.*;
3232
import java.lang.constant.ClassDesc;
33+
import java.lang.constant.DynamicCallSiteDesc;
3334
import java.lang.constant.MethodTypeDesc;
3435
import java.util.Arrays;
3536
import java.util.List;
@@ -521,6 +522,10 @@ public ClassEntry classEntry(ClassDesc cd) {
521522
AbstractPoolEntry.ClassEntryImpl cloneClassEntry(AbstractPoolEntry.ClassEntryImpl e) {
522523
var ce = tryFindClassEntry(e.hashCode(), e.ref1);
523524
if (ce != null) {
525+
var mySym = e.sym;
526+
if (ce.sym == null && mySym != null) {
527+
ce.sym = mySym;
528+
}
524529
return ce;
525530
}
526531

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
@@ -716,7 +716,7 @@ private void processLdc(int index) {
716716
case TAG_METHOD_TYPE ->
717717
currentFrame.pushStack(Type.METHOD_TYPE);
718718
case TAG_DYNAMIC ->
719-
currentFrame.pushStack(cp.entryByIndex(index, ConstantDynamicEntry.class).asSymbol().constantType());
719+
currentFrame.pushStack(cp.entryByIndex(index, ConstantDynamicEntry.class).typeSymbol());
720720
default ->
721721
throw generatorError("CP entry #%d %s is not loadable constant".formatted(index, cp.entryByIndex(index).tag()));
722722
}

0 commit comments

Comments
 (0)