diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 806d3339f5f6b..51748e38454bb 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -32,6 +32,7 @@ import java.lang.classfile.*; import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; import java.lang.classfile.attribute.SourceFileAttribute; +import java.lang.classfile.constantpool.FieldRefEntry; import java.lang.classfile.instruction.SwitchCase; import java.lang.constant.ClassDesc; import java.lang.constant.ConstantDesc; @@ -196,35 +197,9 @@ private static String makeDumpableClassName(String className) { return buf.toString(); } - static class ClassData { - final String name; - final ClassDesc desc; - final Object value; - - ClassData(String name, ClassDesc desc, Object value) { - this.name = name; - this.desc = desc; - this.value = value; - } - - public String name() { return name; } - public String toString() { - return name + ",value="+value; - } - } - - String classData(Object arg) { - ClassDesc desc; - if (arg instanceof Class) { - desc = CD_Class; - } else if (arg instanceof MethodHandle) { - desc = CD_MethodHandle; - } else if (arg instanceof LambdaForm) { - desc = CD_LambdaForm; - } else { - desc = CD_Object; - } + record ClassData(FieldRefEntry field, Object value) {} + FieldRefEntry classData(ClassFileBuilder cfb, Object arg, ClassDesc desc) { // unique static variable name String name; List classData = this.classData; @@ -237,8 +212,9 @@ String classData(Object arg) { } else { name = "_D_" + classData.size(); } - classData.add(new ClassData(name, desc, arg)); - return name; + var field = cfb.constantPool().fieldRefEntry(classDesc, name, desc); + classData.add(new ClassData(field, arg)); + return field; } /** @@ -328,27 +304,31 @@ public void accept(CodeBuilder cob) { .invokestatic(CD_MethodHandles, "classData", MTD_Object_Class); int size = classData.size(); if (size == 1) { - ClassData p = classData.get(0); + var field = classData.getFirst().field; // add the static field - clb.withField(p.name, p.desc, ACC_STATIC | ACC_FINAL); + clb.withField(field.name(), field.type(), ACC_STATIC | ACC_FINAL); - cob.checkcast(p.desc) - .putstatic(classDesc, p.name, p.desc); + var ft = field.typeSymbol(); + if (ft != CD_Object) + cob.checkcast(ft); + cob.putstatic(field); } else { cob.checkcast(CD_List) .astore(0); int index = 0; var listGet = cob.constantPool().interfaceMethodRefEntry(CD_List, "get", MTD_Object_int); for (int i = 0; i < size; i++) { - ClassData p = classData.get(i); + var field = classData.get(i).field; // add the static field - clb.withField(p.name, p.desc, ACC_STATIC | ACC_FINAL); + clb.withField(field.name(), field.type(), ACC_STATIC | ACC_FINAL); // initialize the static field cob.aload(0) .loadConstant(index++) - .invokeinterface(listGet) - .checkcast(p.desc) - .putstatic(classDesc, p.name, p.desc); + .invokeinterface(listGet); + var ft = field.typeSymbol(); + if (ft != CD_Object) + cob.checkcast(ft); + cob.putstatic(field); } } cob.return_(); @@ -366,8 +346,6 @@ private void emitStoreInsn(CodeBuilder cob, TypeKind type, int index) { /** * Emit a boxing call. - * - * @param wrapper primitive type class to box. */ private void emitBoxing(CodeBuilder cob, TypeKind tk) { TypeConvertingMethodAdapter.box(cob, tk); @@ -375,8 +353,6 @@ private void emitBoxing(CodeBuilder cob, TypeKind tk) { /** * Emit an unboxing call (plus preceding checkcast). - * - * @param wrapper wrapper type class to unbox. */ private void emitUnboxing(CodeBuilder cob, TypeKind target) { switch (target) { @@ -445,7 +421,7 @@ private void emitReferenceCast(CodeBuilder cob, Class cls, Object arg) { ClassDesc sig = classDesc(cls); cob.checkcast(sig); } else { - cob.getstatic(classDesc, classData(cls), CD_Class) + cob.getstatic(classData(cob, cls, CD_Class)) .swap() .invokevirtual(CD_Class, "cast", MTD_Object_Object); if (Object[].class.isAssignableFrom(cls)) @@ -554,7 +530,7 @@ private boolean checkActualReceiver(CodeBuilder cob) { * Generate an invoker method for the passed {@link LambdaForm}. */ private byte[] generateCustomizedCodeBytes() { - final byte[] classFile = classFileSetup(new Consumer() { + final byte[] classFile = classFileSetup(new Consumer<>() { @Override public void accept(ClassBuilder clb) { addMethod(clb); @@ -566,7 +542,7 @@ public void accept(ClassBuilder clb) { } void addMethod(ClassBuilder clb) { - methodSetup(clb, new Consumer() { + methodSetup(clb, new Consumer<>() { @Override public void accept(MethodBuilder mb) { @@ -576,9 +552,9 @@ public void accept(MethodBuilder mb) { mb.accept(LF_DONTINLINE_ANNOTATIONS); } - classData(lambdaForm); // keep LambdaForm instance & its compiled form lifetime tightly coupled. + classData(mb, lambdaForm, CD_LambdaForm); // keep LambdaForm instance & its compiled form lifetime tightly coupled. - mb.withCode(new Consumer() { + mb.withCode(new Consumer<>() { @Override public void accept(CodeBuilder cob) { if (lambdaForm.customized != null) { @@ -586,8 +562,7 @@ public void accept(CodeBuilder cob) { // receiver MethodHandle (at slot #0) with an embedded constant and use it instead. // It enables more efficient code generation in some situations, since embedded constants // are compile-time constants for JIT compiler. - cob.getstatic(classDesc, classData(lambdaForm.customized), CD_MethodHandle) - .checkcast(CD_MethodHandle); + cob.getstatic(classData(cob, lambdaForm.customized, CD_MethodHandle)); assert(checkActualReceiver(cob)); // expects MethodHandle on top of the stack cob.astore(0); } @@ -720,7 +695,7 @@ void emitInvoke(CodeBuilder cob, Name name) { // push receiver MethodHandle target = name.function.resolvedHandle(); assert(target != null) : name.exprString(); - cob.getstatic(classDesc, classData(target), CD_MethodHandle); + cob.getstatic(classData(cob, target, CD_MethodHandle)); emitReferenceCast(cob, MethodHandle.class, target); } else { // load receiver @@ -1445,7 +1420,7 @@ private void emitPushArgument(CodeBuilder cob, Class ptype, Object arg) { if (Wrapper.isWrapperType(arg.getClass()) && bptype != L_TYPE) { cob.loadConstant((ConstantDesc)arg); } else { - cob.getstatic(classDesc, classData(arg), CD_Object); + cob.getstatic(classData(cob, arg, CD_Object)); emitImplicitConversion(cob, L_TYPE, ptype, arg); } } @@ -1524,10 +1499,10 @@ static MemberName generateLambdaFormInterpreterEntryPoint(MethodType mt) { } private byte[] generateLambdaFormInterpreterEntryPointBytes() { - final byte[] classFile = classFileSetup(new Consumer() { + final byte[] classFile = classFileSetup(new Consumer<>() { @Override public void accept(ClassBuilder clb) { - methodSetup(clb, new Consumer() { + methodSetup(clb, new Consumer<>() { @Override public void accept(MethodBuilder mb) { @@ -1536,7 +1511,7 @@ public void accept(MethodBuilder mb) { DONTINLINE // Don't inline the interpreter entry. ))); - mb.withCode(new Consumer() { + mb.withCode(new Consumer<>() { @Override public void accept(CodeBuilder cob) { // create parameter array @@ -1593,10 +1568,10 @@ static MemberName generateNamedFunctionInvoker(MethodTypeForm typeForm) { private byte[] generateNamedFunctionInvokerImpl(MethodTypeForm typeForm) { MethodType dstType = typeForm.erasedType(); - final byte[] classFile = classFileSetup(new Consumer() { + final byte[] classFile = classFileSetup(new Consumer<>() { @Override public void accept(ClassBuilder clb) { - methodSetup(clb, new Consumer() { + methodSetup(clb, new Consumer<>() { @Override public void accept(MethodBuilder mb) { @@ -1605,7 +1580,7 @@ public void accept(MethodBuilder mb) { FORCEINLINE // Force inlining of this invoker method. ))); - mb.withCode(new Consumer() { + mb.withCode(new Consumer<>() { @Override public void accept(CodeBuilder cob) { // Load receiver