8295302: Do not use ArrayList when LambdaForm has a single ClassData
Reviewed-by: vlivanov, redestad, mchung
This commit is contained in:
parent
017e7988b1
commit
8d4c077218
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2022, 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
|
||||
@ -285,24 +285,6 @@ class InvokerBytecodeGenerator {
|
||||
return name;
|
||||
}
|
||||
|
||||
List<Object> classDataValues() {
|
||||
final List<ClassData> cd = classData;
|
||||
return switch(cd.size()) {
|
||||
case 0 -> List.of();
|
||||
case 1 -> List.of(cd.get(0).value);
|
||||
case 2 -> List.of(cd.get(0).value, cd.get(1).value);
|
||||
case 3 -> List.of(cd.get(0).value, cd.get(1).value, cd.get(2).value);
|
||||
case 4 -> List.of(cd.get(0).value, cd.get(1).value, cd.get(2).value, cd.get(3).value);
|
||||
default -> {
|
||||
Object[] data = new Object[classData.size()];
|
||||
for (int i = 0; i < classData.size(); i++) {
|
||||
data[i] = classData.get(i).value;
|
||||
}
|
||||
yield List.of(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static String debugString(Object arg) {
|
||||
if (arg instanceof MethodHandle mh) {
|
||||
MemberName member = mh.internalMemberName();
|
||||
@ -360,6 +342,32 @@ class InvokerBytecodeGenerator {
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class data object that will be passed to `Lookup.defineHiddenClassWithClassData`.
|
||||
* The classData is loaded in the <clinit> method of the generated class.
|
||||
* If the class data contains only one single object, this method returns that single object.
|
||||
* If the class data contains more than one objects, this method returns a List.
|
||||
*
|
||||
* This method returns null if no class data.
|
||||
*/
|
||||
private Object classDataValues() {
|
||||
final List<ClassData> cd = classData;
|
||||
return switch (cd.size()) {
|
||||
case 0 -> null; // special case (classData is not used by <clinit>)
|
||||
case 1 -> cd.get(0).value; // special case (single object)
|
||||
case 2 -> List.of(cd.get(0).value, cd.get(1).value);
|
||||
case 3 -> List.of(cd.get(0).value, cd.get(1).value, cd.get(2).value);
|
||||
case 4 -> List.of(cd.get(0).value, cd.get(1).value, cd.get(2).value, cd.get(3).value);
|
||||
default -> {
|
||||
Object[] data = new Object[classData.size()];
|
||||
for (int i = 0; i < classData.size(); i++) {
|
||||
data[i] = classData.get(i).value;
|
||||
}
|
||||
yield List.of(data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* <clinit> to initialize the static final fields with the live class data
|
||||
* LambdaForms can't use condy due to bootstrapping issue.
|
||||
@ -379,18 +387,23 @@ class InvokerBytecodeGenerator {
|
||||
mv.visitLdcInsn(Type.getType("L" + className + ";"));
|
||||
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/invoke/MethodHandles",
|
||||
"classData", "(Ljava/lang/Class;)Ljava/lang/Object;", false);
|
||||
// we should optimize one single element case that does not need to create a List
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, "java/util/List");
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 0);
|
||||
int index = 0;
|
||||
for (ClassData p : classData) {
|
||||
// initialize the static field
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
emitIconstInsn(mv, index++);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List",
|
||||
"get", "(I)Ljava/lang/Object;", true);
|
||||
if (classData.size() == 1) {
|
||||
ClassData p = classData.get(0);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, p.desc.substring(1, p.desc.length()-1));
|
||||
mv.visitFieldInsn(Opcodes.PUTSTATIC, className, p.name, p.desc);
|
||||
} else {
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, "java/util/List");
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 0);
|
||||
int index = 0;
|
||||
for (ClassData p : classData) {
|
||||
// initialize the static field
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
emitIconstInsn(mv, index++);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/List",
|
||||
"get", "(I)Ljava/lang/Object;", true);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, p.desc.substring(1, p.desc.length()-1));
|
||||
mv.visitFieldInsn(Opcodes.PUTSTATIC, className, p.name, p.desc);
|
||||
}
|
||||
}
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user