Bug 560569 - [14] generated record class file has some kind of weird
side effect - REF_getField
Change-Id: Iba7fef7b8a208b34c20176925e7cf0202f02e97c
Signed-off-by: Manoj Palat <manpalat@in.ibm.com>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
index 2c37a44..058ed8b 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
@@ -33,7 +33,7 @@
static {
// TESTS_NUMBERS = new int [] { 40 };
// TESTS_RANGE = new int[] { 1, -1 };
-// TESTS_NAMES = new String[] { "testBug560531" };
+// TESTS_NAMES = new String[] { "testBug560569_001" };
}
public static Class<?> testClass() {
@@ -2038,4 +2038,41 @@
},
"0");
}
+public void testBug560569_001() throws Exception {
+ runConformTest(
+ new String[] {
+ "X.java",
+ "interface Rentable { int year(); }\n"+
+ "record Car(String model, int year) implements Rentable {\n"+
+ " public Car {\n"+
+ " }\n"+
+ " public String toString() {\n"+
+ " return model + \" \" + year;\n"+
+ " }\n"+
+ "}\n"+
+ "record Camel(int year) implements Rentable { }\n"+
+ "\n"+
+ "class X {\n"+
+ " String model;\n"+
+ " int year;\n"+
+ " public String toString() {\n"+
+ " return model + \" \" + year;\n"+
+ " }\n"+
+ " public static void main(String[] args) {\n"+
+ " Car car = new Car(\"Maruti\", 2000);\n"+
+ " System.out.println(car.hashCode() != 0);\n"+
+ " }\n"+
+ "}\n"
+ },
+ "true");
+ String expectedOutput =
+ "Bootstrap methods:\n" +
+ " 0 : # 68 invokestatic java/lang/runtime/ObjectMethods.bootstrap:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/TypeDescriptor;Ljava/lang/Class;Ljava/lang/String;[Ljava/lang/invoke/MethodHandle;)Ljava/lang/Object;\n" +
+ " Method arguments:\n" +
+ " #1 Car\n" +
+ " #69 model;year\n" +
+ " #71 REF_getField model:Ljava/lang/String;\n" +
+ " #72 REF_getField year:I\n";
+ RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "Car.class", ClassFileBytesDisassembler.SYSTEM);
+}
}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
index 7064e79..9533d86 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java
@@ -3721,7 +3721,8 @@
TypeBinding type = recordList.get(i);
assert type.isRecord(); // sanity check
- int recordIndex = this.constantPool.literalIndexForType(type.constantPoolName());
+ char[] recordName = type.constantPoolName();
+ int recordIndex = this.constantPool.literalIndexForType(recordName);
this.contents[localContentsOffset++] = (byte) (recordIndex >> 8);
this.contents[localContentsOffset++] = (byte) recordIndex;
@@ -3742,20 +3743,13 @@
this.contents[localContentsOffset++] = (byte) (namesIndex >> 8);
this.contents[localContentsOffset++] = (byte) namesIndex;
- List<MethodBinding> getters = new ArrayList<>();
for (FieldBinding field : recordComponents) {
- MethodBinding[] candidates = sourceType.getMethods(field.name);
- for (MethodBinding candidate : candidates) {
- if (candidate.parameters == null || candidate.parameters.length == 0) {
- getters.add(candidate);
- break;
- }
- }
- }
- for (MethodBinding getter : getters) {
- int getterIndex = this.constantPool.literalIndexForMethodHandle(getter);
- this.contents[localContentsOffset++] = (byte) (getterIndex >> 8);
- this.contents[localContentsOffset++] = (byte) getterIndex;
+ int methodHandleIndex = this.constantPool.literalIndexForMethodHandleFieldRef(
+ ClassFileConstants.MethodHandleRefKindGetField,
+ recordName, field.name, field.type.signature());
+
+ this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8);
+ this.contents[localContentsOffset++] = (byte) methodHandleIndex;
}
}
return localContentsOffset;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
index 9170fe1..4b31680 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/ConstantPool.java
@@ -886,6 +886,24 @@
return index;
}
+ public int literalIndexForMethodHandleFieldRef(int referenceKind, char[] declaringClass, char[] name, char[] signature) {
+ assert referenceKind == MethodHandleRefKindGetField;
+ int indexForField = literalIndexForField(declaringClass, name, signature);
+
+ int index = this.currentIndex++;
+ int length = this.offsets.length;
+ if (length <= index) {
+ // resize
+ System.arraycopy(this.offsets, 0, (this.offsets = new int[index * 2]), 0, length);
+ }
+
+ this.offsets[index] = this.currentOffset;
+ writeU1(MethodHandleTag);
+ writeU1(referenceKind);
+ writeU2(indexForField);
+
+ return index;
+ }
public int literalIndexForMethodType(char[] descriptor) {
int signatureIndex = literalIndex(descriptor);
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
index 2f38b74..21a8487 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Disassembler.java
@@ -1905,6 +1905,12 @@
ConstantPoolEntry2 constantPoolEntry2 = (ConstantPoolEntry2) constantPoolEntry;
StringBuilder builder = new StringBuilder(10);
switch(constantPoolEntry2.getReferenceKind()) {
+ case IConstantPoolConstant.METHOD_TYPE_REF_GetField:
+ builder.append("REF_getField "); //$NON-NLS-1$
+ constantPoolEntry = (ConstantPoolEntry) constantPool.decodeEntry(constantPoolEntry2.getReferenceIndex());
+ builder.append(Messages.bind("{0}:{1}", fieldDescription(constantPoolEntry))); //$NON-NLS-1$
+ arguments[i] = builder.toString();
+ break;
case IConstantPoolConstant.METHOD_TYPE_REF_InvokeStatic:
builder.append("invokestatic "); //$NON-NLS-1$
//$FALL-THROUGH$
@@ -1919,11 +1925,22 @@
case IConstantPoolConstant.CONSTANT_MethodType:
arguments[i] = new String(((ConstantPoolEntry2) constantPoolEntry).getMethodDescriptor());
break;
+ case IConstantPoolConstant.CONSTANT_Class:
+ arguments[i] = new String(constantPoolEntry.getClassInfoName());
+ break;
+ case IConstantPoolConstant.CONSTANT_String:
+ arguments[i] = constantPoolEntry.getStringValue();
+ break;
}
}
return arguments;
}
+ private String[] fieldDescription(IConstantPoolEntry constantPoolEntry) {
+ return new String[] { new String(constantPoolEntry.getFieldName()),
+ new String(constantPoolEntry.getFieldDescriptor())};
+ }
+
private String[] methodDescription(IConstantPoolEntry constantPoolEntry) {
return new String[] { new String(constantPoolEntry.getClassName()),
new String(constantPoolEntry.getMethodName()),