mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
8338545: Functional interface implementations for common pre-boot ClassFile operations
Reviewed-by: asotona
This commit is contained in:
parent
7458952ded
commit
80adea8e0a
11 changed files with 76 additions and 106 deletions
|
@ -165,7 +165,7 @@ public sealed interface ClassBuilder
|
|||
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 @@ public sealed interface ClassBuilder
|
|||
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 @@ public sealed interface ClassBuilder
|
|||
Utf8Entry descriptor,
|
||||
int methodFlags,
|
||||
Consumer<? super CodeBuilder> handler) {
|
||||
return withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler));
|
||||
return withMethod(name, descriptor, methodFlags, Util.buildingCode(handler));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -276,7 +276,7 @@ public sealed interface ClassBuilder
|
|||
MethodTypeDesc descriptor,
|
||||
int methodFlags,
|
||||
Consumer<? super CodeBuilder> handler) {
|
||||
return withMethod(name, descriptor, methodFlags, mb -> mb.withCode(handler));
|
||||
return withMethod(name, descriptor, methodFlags, Util.buildingCode(handler));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.classfile.attribute.SourceFileAttribute;
|
|||
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<T,K,S extends ClassSpecializer<T,K,S>.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<FieldBuilder> STATIC_FIELD_FLAGS = new InnerClassLambdaMetafactory.FieldFlags(ACC_STATIC);
|
||||
private static final Consumer<FieldBuilder> FINAL_FIELD_FLAGS = new InnerClassLambdaMetafactory.FieldFlags(ACC_FINAL);
|
||||
|
||||
private final Class<T> topClass;
|
||||
private final Class<K> keyType;
|
||||
|
@ -625,7 +622,7 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat
|
|||
.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 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat
|
|||
|
||||
// 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<CodeBuilder>() {
|
||||
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<CodeBuilder>() {
|
||||
clb.withMethodBody(INIT_NAME, methodDesc(thisCtorType), ACC_PRIVATE,
|
||||
new Consumer<>() {
|
||||
@Override
|
||||
public void accept(CodeBuilder cob) {
|
||||
cob.aload(0); // this
|
||||
|
@ -753,12 +750,12 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat
|
|||
|
||||
cob.return_();
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
// emit make() ...factory method wrapping constructor
|
||||
MethodType ftryType = thisCtorType.changeReturnType(topClass());
|
||||
clb.withMethod("make", methodDesc(ftryType), ACC_STATIC,
|
||||
new MethodBody(new Consumer<CodeBuilder>() {
|
||||
clb.withMethodBody("make", methodDesc(ftryType), ACC_STATIC,
|
||||
new Consumer<>() {
|
||||
@Override
|
||||
public void accept(CodeBuilder cob) {
|
||||
// make instance
|
||||
|
@ -773,7 +770,7 @@ abstract class ClassSpecializer<T,K,S extends ClassSpecializer<T,K,S>.SpeciesDat
|
|||
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
|
||||
|
|
|
@ -72,20 +72,6 @@ import sun.invoke.util.Wrapper;
|
|||
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<FieldBuilder> {
|
||||
@Override
|
||||
public void accept(FieldBuilder fb) {
|
||||
fb.withFlags(flags);
|
||||
}
|
||||
};
|
||||
record MethodBody(Consumer<CodeBuilder> code) implements Consumer<MethodBuilder> {
|
||||
@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 @@ import sun.invoke.util.Wrapper;
|
|||
.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 @@ import sun.invoke.util.Wrapper;
|
|||
}
|
||||
|
||||
// Forward the SAM method
|
||||
clb.withMethod(interfaceMethodName,
|
||||
clb.withMethodBody(interfaceMethodName,
|
||||
methodDesc(interfaceMethodType),
|
||||
ACC_PUBLIC,
|
||||
forwardingMethod(interfaceMethodType));
|
||||
|
@ -342,7 +328,7 @@ import sun.invoke.util.Wrapper;
|
|||
// 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 @@ import sun.invoke.util.Wrapper;
|
|||
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<CodeBuilder>() {
|
||||
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 @@ import sun.invoke.util.Wrapper;
|
|||
.putstatic(lambdaClassDesc, LAMBDA_INSTANCE_FIELD, lambdaTypeDescriptor)
|
||||
.return_();
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -397,8 +383,8 @@ import sun.invoke.util.Wrapper;
|
|||
*/
|
||||
private void generateConstructor(ClassBuilder clb) {
|
||||
// Generate constructor
|
||||
clb.withMethod(INIT_NAME, constructorTypeDesc, ACC_PRIVATE,
|
||||
new MethodBody(new Consumer<CodeBuilder>() {
|
||||
clb.withMethodBody(INIT_NAME, constructorTypeDesc, ACC_PRIVATE,
|
||||
new Consumer<>() {
|
||||
@Override
|
||||
public void accept(CodeBuilder cob) {
|
||||
cob.aload(0)
|
||||
|
@ -412,7 +398,7 @@ import sun.invoke.util.Wrapper;
|
|||
}
|
||||
cob.return_();
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
private static class SerializationSupport {
|
||||
|
@ -439,8 +425,8 @@ import sun.invoke.util.Wrapper;
|
|||
* 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<CodeBuilder>() {
|
||||
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 @@ import sun.invoke.util.Wrapper;
|
|||
SerializationSupport.MTD_CTOR_SERIALIZED_LAMBDA)
|
||||
.areturn();
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -504,8 +490,8 @@ import sun.invoke.util.Wrapper;
|
|||
* This method generates a method body which calls the lambda implementation
|
||||
* method, converting arguments, as needed.
|
||||
*/
|
||||
Consumer<MethodBuilder> forwardingMethod(MethodType methodType) {
|
||||
return new MethodBody(new Consumer<CodeBuilder>() {
|
||||
Consumer<CodeBuilder> forwardingMethod(MethodType methodType) {
|
||||
return new Consumer<>() {
|
||||
@Override
|
||||
public void accept(CodeBuilder cob) {
|
||||
if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
|
||||
|
@ -542,7 +528,7 @@ import sun.invoke.util.Wrapper;
|
|||
TypeConvertingMethodAdapter.convertType(cob, implReturnClass, samReturnClass, samReturnClass);
|
||||
cob.return_(TypeKind.from(samReturnClass));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private void convertArgumentTypes(CodeBuilder cob, MethodType samType) {
|
||||
|
|
|
@ -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<FieldBuilder> STATIC_FINAL_FIELD = new Consumer<FieldBuilder>() {
|
||||
@Override
|
||||
public void accept(FieldBuilder fb) {
|
||||
fb.withFlags(ACC_STATIC | ACC_FINAL);
|
||||
}
|
||||
};
|
||||
|
||||
record MethodBody(Consumer<CodeBuilder> code) implements Consumer<MethodBuilder> {
|
||||
@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 @@ class InvokerBytecodeGenerator {
|
|||
|
||||
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<CodeBuilder>() {
|
||||
clb.withMethodBody(CLASS_INIT_NAME, MTD_void, ACC_STATIC, new Consumer<>() {
|
||||
@Override
|
||||
public void accept(CodeBuilder cob) {
|
||||
cob.loadConstant(classDesc)
|
||||
|
@ -356,7 +341,7 @@ class InvokerBytecodeGenerator {
|
|||
}
|
||||
cob.return_();
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
private void emitLoadInsn(CodeBuilder cob, TypeKind type, int index) {
|
||||
|
@ -1671,14 +1656,14 @@ class InvokerBytecodeGenerator {
|
|||
*/
|
||||
private void bogusMethod(ClassBuilder clb, Object os) {
|
||||
if (dumper().isEnabled()) {
|
||||
clb.withMethod("dummy", MTD_void, ACC_STATIC, new MethodBody(new Consumer<CodeBuilder>() {
|
||||
clb.withMethodBody("dummy", MTD_void, ACC_STATIC, new Consumer<>() {
|
||||
@Override
|
||||
public void accept(CodeBuilder cob) {
|
||||
cob.loadConstant(os.toString());
|
||||
cob.pop();
|
||||
cob.return_();
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue