From a9bb04331df6788561921202cac73e35afbfe314 Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Mon, 9 Sep 2024 15:15:16 +0000 Subject: [PATCH] 8339683: Simplify class data generation in InvokerBytecodeGenerator Reviewed-by: redestad --- .../lang/invoke/GenerateJLIClassesHelper.java | 2 +- .../lang/invoke/InvokerBytecodeGenerator.java | 97 +++++++------------ 2 files changed, 38 insertions(+), 61 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index 1e3f465f97d..a9497502ec6 100644 --- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -563,7 +563,7 @@ class GenerateJLIClassesHelper { .withSuperclass(InvokerBytecodeGenerator.INVOKER_SUPER_DESC) .with(SourceFileAttribute.of(className.substring(className.lastIndexOf('/') + 1))); for (int i = 0; i < forms.length; i++) { - new InvokerBytecodeGenerator(className, names[i], forms[i], forms[i].methodType()).addMethod(clb); + new InvokerBytecodeGenerator(className, names[i], forms[i], forms[i].methodType()).addMethod(clb, false); } }); } 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 806d3339f5f..7d46eb85ce6 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 sun.invoke.util.Wrapper; 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 @@ class InvokerBytecodeGenerator { 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 @@ class InvokerBytecodeGenerator { } 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 @@ class InvokerBytecodeGenerator { .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 @@ class InvokerBytecodeGenerator { /** * 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 @@ class InvokerBytecodeGenerator { /** * 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 @@ class InvokerBytecodeGenerator { 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,10 +530,10 @@ class InvokerBytecodeGenerator { * 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); + addMethod(clb, true); clinit(clb, classDesc, classData); bogusMethod(clb, lambdaForm); } @@ -565,8 +541,8 @@ class InvokerBytecodeGenerator { return classFile; } - void addMethod(ClassBuilder clb) { - methodSetup(clb, new Consumer() { + void addMethod(ClassBuilder clb, boolean alive) { + methodSetup(clb, new Consumer<>() { @Override public void accept(MethodBuilder mb) { @@ -576,9 +552,11 @@ class InvokerBytecodeGenerator { mb.accept(LF_DONTINLINE_ANNOTATIONS); } - classData(lambdaForm); // keep LambdaForm instance & its compiled form lifetime tightly coupled. + if (alive) { + 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 +564,7 @@ class InvokerBytecodeGenerator { // 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 +697,7 @@ class InvokerBytecodeGenerator { // 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 +1422,7 @@ class InvokerBytecodeGenerator { 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 +1501,10 @@ class InvokerBytecodeGenerator { } 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 +1513,7 @@ class InvokerBytecodeGenerator { 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 +1570,10 @@ class InvokerBytecodeGenerator { 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 +1582,7 @@ class InvokerBytecodeGenerator { FORCEINLINE // Force inlining of this invoker method. ))); - mb.withCode(new Consumer() { + mb.withCode(new Consumer<>() { @Override public void accept(CodeBuilder cob) { // Load receiver