Skip to content

Commit

Permalink
8295302: Do not use ArrayList when LambdaForm has a single ClassData
Browse files Browse the repository at this point in the history
Reviewed-by: vlivanov, redestad, mchung
  • Loading branch information
iklam committed Oct 19, 2022
1 parent 017e798 commit 8d4c077
Showing 1 changed file with 42 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -285,24 +285,6 @@ String classData(Object arg) {
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();
Expand Down Expand Up @@ -360,6 +342,32 @@ private void methodEpilogue() {
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.
Expand All @@ -379,18 +387,23 @@ static void clinit(ClassWriter cw, String className, List<ClassData> classData)
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);
Expand Down

1 comment on commit 8d4c077

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.