|
34 | 34 | import java.lang.classfile.ClassBuilder; |
35 | 35 | import java.lang.classfile.ClassFile; |
36 | 36 | import java.lang.classfile.CodeBuilder; |
37 | | -import java.lang.classfile.FieldBuilder; |
38 | 37 | import java.lang.classfile.MethodBuilder; |
39 | 38 | import java.lang.classfile.Opcode; |
40 | 39 | import java.lang.classfile.TypeKind; |
41 | 40 | import java.lang.constant.ClassDesc; |
42 | | -import java.lang.constant.DynamicConstantDesc; |
43 | 41 | import java.lang.constant.MethodTypeDesc; |
44 | 42 | import java.lang.reflect.Modifier; |
45 | 43 | import java.util.LinkedHashSet; |
|
51 | 49 | import java.lang.classfile.attribute.ExceptionsAttribute; |
52 | 50 | import java.lang.classfile.constantpool.ClassEntry; |
53 | 51 | import java.lang.classfile.constantpool.ConstantPoolBuilder; |
54 | | -import java.lang.classfile.constantpool.MethodRefEntry; |
| 52 | + |
55 | 53 | import static java.lang.constant.ConstantDescs.*; |
56 | 54 | import static java.lang.invoke.MethodHandleNatives.Constants.NESTMATE_CLASS; |
57 | 55 | import static java.lang.invoke.MethodHandleNatives.Constants.STRONG_LOADER_LINK; |
58 | | -import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE; |
59 | | -import static java.lang.invoke.MethodHandles.Lookup.ClassOption.STRONG; |
60 | 56 | import static java.lang.invoke.MethodType.methodType; |
61 | 57 | import jdk.internal.constant.ConstantUtils; |
62 | 58 | import jdk.internal.constant.MethodTypeDescImpl; |
63 | 59 | import jdk.internal.constant.ReferenceClassDescImpl; |
| 60 | +import jdk.internal.vm.annotation.Stable; |
64 | 61 | import sun.invoke.util.Wrapper; |
65 | 62 |
|
66 | 63 | /** |
|
71 | 68 | */ |
72 | 69 | /* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { |
73 | 70 | private static final String LAMBDA_INSTANCE_FIELD = "LAMBDA_INSTANCE$"; |
74 | | - private static final String[] EMPTY_STRING_ARRAY = new String[0]; |
| 71 | + private static final @Stable String[] ARG_NAME_CACHE = {"arg$1", "arg$2", "arg$3", "arg$4", "arg$5", "arg$6", "arg$7", "arg$8"}; |
75 | 72 | private static final ClassDesc[] EMPTY_CLASSDESC_ARRAY = ConstantUtils.EMPTY_CLASSDESC; |
76 | 73 |
|
77 | 74 | // For dumping generated classes to disk, for debugging purposes |
|
96 | 93 | private final MethodTypeDesc implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;" |
97 | 94 | private final MethodType constructorType; // Generated class constructor type "(CC)void" |
98 | 95 | private final MethodTypeDesc constructorTypeDesc;// Type descriptor for the generated class constructor type "(CC)void" |
99 | | - private final String[] argNames; // Generated names for the constructor arguments |
100 | 96 | private final ClassDesc[] argDescs; // Type descriptors for the constructor arguments |
101 | 97 | private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1" |
102 | 98 | private final ConstantPoolBuilder pool = ConstantPoolBuilder.of(); |
@@ -174,18 +170,24 @@ public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, |
174 | 170 | implKind == MethodHandleInfo.REF_invokeSpecial || |
175 | 171 | implKind == MethodHandleInfo.REF_invokeStatic && implClass.isHidden(); |
176 | 172 | int parameterCount = factoryType.parameterCount(); |
| 173 | + ClassDesc[] argDescs; |
| 174 | + MethodTypeDesc constructorTypeDesc; |
177 | 175 | if (parameterCount > 0) { |
178 | | - argNames = new String[parameterCount]; |
179 | 176 | argDescs = new ClassDesc[parameterCount]; |
180 | 177 | for (int i = 0; i < parameterCount; i++) { |
181 | | - argNames[i] = "arg$" + (i + 1); |
182 | 178 | argDescs[i] = classDesc(factoryType.parameterType(i)); |
183 | 179 | } |
| 180 | + constructorTypeDesc = MethodTypeDescImpl.ofValidated(CD_void, argDescs); |
184 | 181 | } else { |
185 | | - argNames = EMPTY_STRING_ARRAY; |
186 | 182 | argDescs = EMPTY_CLASSDESC_ARRAY; |
| 183 | + constructorTypeDesc = MTD_void; |
187 | 184 | } |
188 | | - constructorTypeDesc = MethodTypeDescImpl.ofValidated(CD_void, argDescs); |
| 185 | + this.argDescs = argDescs; |
| 186 | + this.constructorTypeDesc = constructorTypeDesc; |
| 187 | + } |
| 188 | + |
| 189 | + private static String argName(int i) { |
| 190 | + return i < ARG_NAME_CACHE.length ? ARG_NAME_CACHE[i] : "arg$" + (i + 1); |
189 | 191 | } |
190 | 192 |
|
191 | 193 | private static String lambdaClassName(Class<?> targetClass) { |
@@ -313,7 +315,7 @@ public void accept(ClassBuilder clb) { |
313 | 315 | .withInterfaceSymbols(interfaces); |
314 | 316 | // Generate final fields to be filled in by constructor |
315 | 317 | for (int i = 0; i < argDescs.length; i++) { |
316 | | - clb.withField(argNames[i], argDescs[i], ACC_PRIVATE | ACC_FINAL); |
| 318 | + clb.withField(argName(i), argDescs[i], ACC_PRIVATE | ACC_FINAL); |
317 | 319 | } |
318 | 320 |
|
319 | 321 | generateConstructor(clb); |
@@ -396,7 +398,7 @@ public void accept(CodeBuilder cob) { |
396 | 398 | for (int i = 0; i < parameterCount; i++) { |
397 | 399 | cob.aload(0) |
398 | 400 | .loadLocal(TypeKind.from(factoryType.parameterType(i)), cob.parameterSlot(i)) |
399 | | - .putfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argNames[i], argDescs[i]))); |
| 401 | + .putfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argName(i), argDescs[i]))); |
400 | 402 | } |
401 | 403 | cob.return_(); |
402 | 404 | } |
@@ -448,7 +450,7 @@ public void accept(CodeBuilder cob) { |
448 | 450 | cob.dup() |
449 | 451 | .loadConstant(i) |
450 | 452 | .aload(0) |
451 | | - .getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argNames[i], argDescs[i]))); |
| 453 | + .getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argName(i), argDescs[i]))); |
452 | 454 | TypeConvertingMethodAdapter.boxIfTypePrimitive(cob, TypeKind.from(argDescs[i])); |
453 | 455 | cob.aastore(); |
454 | 456 | } |
@@ -505,9 +507,9 @@ public void accept(CodeBuilder cob) { |
505 | 507 | cob.ldc(cp.constantDynamicEntry(cp.bsmEntry(cp.methodHandleEntry(BSM_CLASS_DATA), List.of()), |
506 | 508 | cp.nameAndTypeEntry(DEFAULT_NAME, CD_MethodHandle))); |
507 | 509 | } |
508 | | - for (int i = 0; i < argNames.length; i++) { |
| 510 | + for (int i = 0; i < argDescs.length; i++) { |
509 | 511 | cob.aload(0) |
510 | | - .getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argNames[i], argDescs[i]))); |
| 512 | + .getfield(pool.fieldRefEntry(lambdaClassEntry, pool.nameAndTypeEntry(argName(i), argDescs[i]))); |
511 | 513 | } |
512 | 514 |
|
513 | 515 | convertArgumentTypes(cob, methodType); |
|
0 commit comments