8339683: Simplify class data generation in InvokerBytecodeGenerator

Reviewed-by: redestad
This commit is contained in:
Chen Liang 2024-09-09 15:15:16 +00:00
parent 7c0f013d92
commit a9bb04331d
2 changed files with 38 additions and 61 deletions

View File

@ -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);
}
});
}

View File

@ -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> 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<ClassBuilder>() {
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<MethodBuilder>() {
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<CodeBuilder>() {
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<ClassBuilder>() {
final byte[] classFile = classFileSetup(new Consumer<>() {
@Override
public void accept(ClassBuilder clb) {
methodSetup(clb, new Consumer<MethodBuilder>() {
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<CodeBuilder>() {
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<ClassBuilder>() {
final byte[] classFile = classFileSetup(new Consumer<>() {
@Override
public void accept(ClassBuilder clb) {
methodSetup(clb, new Consumer<MethodBuilder>() {
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<CodeBuilder>() {
mb.withCode(new Consumer<>() {
@Override
public void accept(CodeBuilder cob) {
// Load receiver