diff --git a/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java b/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java index 98371c9e15a61..1d5bb271dbe21 100644 --- a/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java +++ b/src/java.base/share/classes/java/lang/classfile/ClassBuilder.java @@ -165,7 +165,7 @@ ClassBuilder withField(Utf8Entry name, default ClassBuilder withField(Utf8Entry name, Utf8Entry descriptor, int flags) { - return withField(name, descriptor, fb -> fb.withFlags(flags)); + return withField(name, descriptor, Util.buildingFlags(flags)); } /** @@ -194,7 +194,7 @@ default ClassBuilder withField(String name, default ClassBuilder withField(String name, ClassDesc descriptor, int flags) { - return withField(name, descriptor, fb -> fb.withFlags(flags)); + return withField(name, descriptor, Util.buildingFlags(flags)); } /** @@ -241,7 +241,7 @@ default ClassBuilder withMethodBody(Utf8Entry name, Utf8Entry descriptor, int methodFlags, Consumer handler) { - return withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler)); + return withMethod(name, descriptor, methodFlags, Util.buildingCode(handler)); } /** @@ -276,7 +276,7 @@ default ClassBuilder withMethodBody(String name, MethodTypeDesc descriptor, int methodFlags, Consumer handler) { - return withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler)); + return withMethod(name, descriptor, methodFlags, Util.buildingCode(handler)); } /** diff --git a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java index 1df3b3c662825..94a271780c32e 100644 --- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java +++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.lang.invoke.LambdaForm.BasicType; -import java.lang.invoke.InnerClassLambdaMetafactory.MethodBody; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -68,8 +67,6 @@ abstract class ClassSpecializer.SpeciesDat private static final ClassDesc CD_LambdaForm = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/LambdaForm;"); private static final ClassDesc CD_BoundMethodHandle = ReferenceClassDescImpl.ofValidated("Ljava/lang/invoke/BoundMethodHandle;"); - private static final Consumer STATIC_FIELD_FLAGS = new InnerClassLambdaMetafactory.FieldFlags(ACC_STATIC); - private static final Consumer FINAL_FIELD_FLAGS = new InnerClassLambdaMetafactory.FieldFlags(ACC_FINAL); private final Class topClass; private final Class keyType; @@ -625,7 +622,7 @@ public void accept(ClassBuilder clb) { .with(SourceFileAttribute.of(classDesc.displayName())) // emit static types and BMH_SPECIES fields - .withField(sdFieldName, CD_SPECIES_DATA, STATIC_FIELD_FLAGS); + .withField(sdFieldName, CD_SPECIES_DATA, ACC_STATIC); // handy holder for dealing with groups of typed values (ctor arguments and fields) class Var { @@ -709,26 +706,26 @@ void emitLoadInstruction(CodeBuilder cob) { // emit bound argument fields for (Var field : fields) { - clb.withField(field.name, field.desc, FINAL_FIELD_FLAGS); + clb.withField(field.name, field.desc, ACC_FINAL); } // emit implementation of speciesData() - clb.withMethod(SPECIES_DATA_NAME, MTD_SPECIES_DATA, (SPECIES_DATA_MODS & ACC_PPP) | ACC_FINAL, - new MethodBody(new Consumer() { + clb.withMethodBody(SPECIES_DATA_NAME, MTD_SPECIES_DATA, (SPECIES_DATA_MODS & ACC_PPP) | ACC_FINAL, + new Consumer<>() { @Override public void accept(CodeBuilder cob) { cob.getstatic(classDesc, sdFieldName, CD_SPECIES_DATA) .areturn(); } - })); + }); // figure out the constructor arguments MethodType superCtorType = ClassSpecializer.this.baseConstructorType(); MethodType thisCtorType = superCtorType.appendParameterTypes(fieldTypes); // emit constructor - clb.withMethod(INIT_NAME, methodDesc(thisCtorType), ACC_PRIVATE, - new MethodBody(new Consumer() { + clb.withMethodBody(INIT_NAME, methodDesc(thisCtorType), ACC_PRIVATE, + new Consumer<>() { @Override public void accept(CodeBuilder cob) { cob.aload(0); // this @@ -753,12 +750,12 @@ public void accept(CodeBuilder cob) { cob.return_(); } - })); + }); // emit make() ...factory method wrapping constructor MethodType ftryType = thisCtorType.changeReturnType(topClass()); - clb.withMethod("make", methodDesc(ftryType), ACC_STATIC, - new MethodBody(new Consumer() { + clb.withMethodBody("make", methodDesc(ftryType), ACC_STATIC, + new Consumer<>() { @Override public void accept(CodeBuilder cob) { // make instance @@ -773,7 +770,7 @@ public void accept(CodeBuilder cob) { cob.invokespecial(classDesc, INIT_NAME, methodDesc(thisCtorType)) .areturn(); } - })); + }); // For each transform, emit the customized override of the transform method. // This method mixes together some incoming arguments (from the transform's diff --git a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index ce2547710a5cb..24c97d7f7dc6d 100644 --- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -72,20 +72,6 @@ private static final String[] EMPTY_STRING_ARRAY = new String[0]; private static final ClassDesc[] EMPTY_CLASSDESC_ARRAY = ConstantUtils.EMPTY_CLASSDESC; - // Static builders to avoid lambdas - record FieldFlags(int flags) implements Consumer { - @Override - public void accept(FieldBuilder fb) { - fb.withFlags(flags); - } - }; - record MethodBody(Consumer code) implements Consumer { - @Override - public void accept(MethodBuilder mb) { - mb.withCode(code); - } - }; - // For dumping generated classes to disk, for debugging purposes private static final ClassFileDumper lambdaProxyClassFileDumper; @@ -324,7 +310,7 @@ public void accept(ClassBuilder clb) { .withInterfaceSymbols(interfaces); // Generate final fields to be filled in by constructor for (int i = 0; i < argDescs.length; i++) { - clb.withField(argNames[i], argDescs[i], new FieldFlags(ACC_PRIVATE | ACC_FINAL)); + clb.withField(argNames[i], argDescs[i], ACC_PRIVATE | ACC_FINAL); } generateConstructor(clb); @@ -334,7 +320,7 @@ public void accept(ClassBuilder clb) { } // Forward the SAM method - clb.withMethod(interfaceMethodName, + clb.withMethodBody(interfaceMethodName, methodDesc(interfaceMethodType), ACC_PUBLIC, forwardingMethod(interfaceMethodType)); @@ -342,7 +328,7 @@ public void accept(ClassBuilder clb) { // Forward the bridges if (altMethods != null) { for (MethodType mt : altMethods) { - clb.withMethod(interfaceMethodName, + clb.withMethodBody(interfaceMethodName, methodDesc(mt), ACC_PUBLIC | ACC_BRIDGE, forwardingMethod(mt)); @@ -376,10 +362,10 @@ private void generateClassInitializer(ClassBuilder clb) { ClassDesc lambdaTypeDescriptor = classDesc(factoryType.returnType()); // Generate the static final field that holds the lambda singleton - clb.withField(LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor, new FieldFlags(ACC_PRIVATE | ACC_STATIC | ACC_FINAL)); + clb.withField(LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor, ACC_PRIVATE | ACC_STATIC | ACC_FINAL); // Instantiate the lambda and store it to the static final field - clb.withMethod(CLASS_INIT_NAME, MTD_void, ACC_STATIC, new MethodBody(new Consumer() { + clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, new Consumer<>() { @Override public void accept(CodeBuilder cob) { assert factoryType.parameterCount() == 0; @@ -389,7 +375,7 @@ public void accept(CodeBuilder cob) { .putstatic(lambdaClassDesc, LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor) .return_(); } - })); + }); } /** @@ -397,8 +383,8 @@ public void accept(CodeBuilder cob) { */ private void generateConstructor(ClassBuilder clb) { // Generate constructor - clb.withMethod(INIT_NAME, constructorTypeDesc, ACC_PRIVATE, - new MethodBody(new Consumer() { + clb.withMethodBody(INIT_NAME, constructorTypeDesc, ACC_PRIVATE, + new Consumer<>() { @Override public void accept(CodeBuilder cob) { cob.aload(0) @@ -412,7 +398,7 @@ public void accept(CodeBuilder cob) { } cob.return_(); } - })); + }); } private static class SerializationSupport { @@ -439,8 +425,8 @@ private static class SerializationSupport { * Generate a writeReplace method that supports serialization */ private void generateSerializationFriendlyMethods(ClassBuilder clb) { - clb.withMethod(SerializationSupport.NAME_METHOD_WRITE_REPLACE, SerializationSupport.MTD_Object, ACC_PRIVATE | ACC_FINAL, - new MethodBody(new Consumer() { + clb.withMethodBody(SerializationSupport.NAME_METHOD_WRITE_REPLACE, SerializationSupport.MTD_Object, ACC_PRIVATE | ACC_FINAL, + new Consumer<>() { @Override public void accept(CodeBuilder cob) { cob.new_(SerializationSupport.CD_SerializedLambda) @@ -468,7 +454,7 @@ public void accept(CodeBuilder cob) { SerializationSupport.MTD_CTOR_SERIALIZED_LAMBDA) .areturn(); } - })); + }); } /** @@ -504,8 +490,8 @@ public void accept(CodeBuilder cob) { * This method generates a method body which calls the lambda implementation * method, converting arguments, as needed. */ - Consumer forwardingMethod(MethodType methodType) { - return new MethodBody(new Consumer() { + Consumer forwardingMethod(MethodType methodType) { + return new Consumer<>() { @Override public void accept(CodeBuilder cob) { if (implKind == MethodHandleInfo.REF_newInvokeSpecial) { @@ -542,7 +528,7 @@ public void accept(CodeBuilder cob) { TypeConvertingMethodAdapter.convertType(cob, implReturnClass, samReturnClass, samReturnClass); cob.return_(TypeKind.from(samReturnClass)); } - }); + }; } private void convertArgumentTypes(CodeBuilder cob, MethodType samType) { 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 6d71296c13426..17cf699c536c2 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,21 +83,6 @@ class InvokerBytecodeGenerator { private static final String CLASS_PREFIX = "java/lang/invoke/LambdaForm$"; private static final String SOURCE_PREFIX = "LambdaForm$"; - // Static builders to avoid lambdas - private static final Consumer STATIC_FINAL_FIELD = new Consumer() { - @Override - public void accept(FieldBuilder fb) { - fb.withFlags(ACC_STATIC | ACC_FINAL); - } - }; - - record MethodBody(Consumer code) implements Consumer { - @Override - public void accept(MethodBuilder mb) { - mb.withCode(code); - } - }; - /** Name of its super class*/ static final ClassDesc INVOKER_SUPER_DESC = CD_Object; @@ -328,10 +313,10 @@ static void clinit(ClassBuilder clb, ClassDesc classDesc, List classD for (ClassData p : classData) { // add the static field - clb.withField(p.name, p.desc, STATIC_FINAL_FIELD); + clb.withField(p.name, p.desc, ACC_STATIC | ACC_FINAL); } - clb.withMethod(CLASS_INIT_NAME, MTD_void, ACC_STATIC, new MethodBody(new Consumer() { + clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, new Consumer<>() { @Override public void accept(CodeBuilder cob) { cob.loadConstant(classDesc) @@ -356,7 +341,7 @@ public void accept(CodeBuilder cob) { } cob.return_(); } - })); + }); } private void emitLoadInsn(CodeBuilder cob, TypeKind type, int index) { @@ -1671,14 +1656,14 @@ public void accept(CodeBuilder cob) { */ private void bogusMethod(ClassBuilder clb, Object os) { if (dumper().isEnabled()) { - clb.withMethod("dummy", MTD_void, ACC_STATIC, new MethodBody(new Consumer() { + clb.withMethodBody("dummy", MTD_void, ACC_STATIC, new Consumer<>() { @Override public void accept(CodeBuilder cob) { cob.loadConstant(os.toString()); cob.pop(); cob.return_(); } - })); + }); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java index b690f8dbfe70a..c506d265f6895 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedCodeBuilder.java @@ -173,12 +173,7 @@ public Optional parent() { @Override public void writeTo(DirectMethodBuilder builder) { - builder.withCode(new Consumer<>() { - @Override - public void accept(CodeBuilder cb) { - forEach(cb); - } - }); + builder.withCode(Util.writingAll(this)); } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java index d165ddd3928fd..8cf274d746c1c 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedFieldBuilder.java @@ -104,12 +104,7 @@ public Utf8Entry fieldType() { @Override public void writeTo(DirectClassBuilder builder) { - builder.withField(name, desc, new Consumer<>() { - @Override - public void accept(FieldBuilder fieldBuilder) { - elements.forEach(fieldBuilder); - } - }); + builder.withField(name, desc, Util.writingAll(this)); } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java index 4a9e9b111ce08..84ddd09b990ec 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufferedMethodBuilder.java @@ -205,12 +205,7 @@ public Optional code() { @Override public void writeTo(DirectClassBuilder builder) { - builder.withMethod(methodName(), methodType(), methodFlags(), new Consumer<>() { - @Override - public void accept(MethodBuilder mb) { - forEach(mb); - } - }); + builder.withMethod(methodName(), methodType(), methodFlags(), Util.writingAll(this)); } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java index d4719fad0b1c2..8be7e92f5b600 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/CodeImpl.java @@ -147,12 +147,7 @@ public void writeTo(BufWriterImpl buf) { } else { DirectCodeBuilder.build((MethodInfo) enclosingMethod, - new Consumer() { - @Override - public void accept(CodeBuilder cb) { - forEach(cb); - } - }, + Util.writingAll(this), (SplitConstantPool)buf.constantPool(), buf.context(), null).writeTo(buf); diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java index a71593a57120e..30bb8136e45ab 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/FieldImpl.java @@ -99,12 +99,7 @@ public void writeTo(DirectClassBuilder builder) { builder.withField(this); } else { - builder.withField(fieldName(), fieldType(), new Consumer<>() { - @Override - public void accept(FieldBuilder fb) { - FieldImpl.this.forEach(fb); - } - }); + builder.withField(fieldName(), fieldType(), Util.writingAll(this)); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java index 032b18600a897..05de881ba297f 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/MethodImpl.java @@ -136,13 +136,7 @@ public void writeTo(DirectClassBuilder builder) { builder.withMethod(this); } else { - builder.withMethod(methodName(), methodType(), methodFlags(), - new Consumer<>() { - @Override - public void accept(MethodBuilder mb) { - MethodImpl.this.forEach(mb); - } - }); + builder.withMethod(methodName(), methodType(), methodFlags(), Util.writingAll(this)); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java index 079ac9551aba6..1ff80d766766e 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java @@ -24,7 +24,10 @@ */ package jdk.internal.classfile.impl; +import java.lang.classfile.CodeBuilder; import java.lang.classfile.CustomAttribute; +import java.lang.classfile.FieldBuilder; +import java.lang.classfile.MethodBuilder; import java.lang.classfile.PseudoInstruction; import java.lang.classfile.constantpool.PoolEntry; import java.lang.constant.ClassDesc; @@ -63,6 +66,36 @@ public class Util { private Util() { } + public static Consumer> writingAll(Iterable container) { + record ForEachConsumer(Iterable container) implements Consumer> { + @Override + public void accept(Consumer consumer) { + container.forEach(consumer); + } + } + return new ForEachConsumer<>(container); + } + + public static Consumer buildingCode(Consumer codeHandler) { + record WithCodeMethodHandler(Consumer codeHandler) implements Consumer { + @Override + public void accept(MethodBuilder builder) { + builder.withCode(codeHandler); + } + } + return new WithCodeMethodHandler(codeHandler); + } + + public static Consumer buildingFlags(int flags) { + record WithFlagFieldHandler(int flags) implements Consumer { + @Override + public void accept(FieldBuilder builder) { + builder.withFlags(flags); + } + } + return new WithFlagFieldHandler(flags); + } + private static final int ATTRIBUTE_STABILITY_COUNT = AttributeMapper.AttributeStability.values().length; public static boolean isAttributeAllowed(final Attribute attr,