diff options
author | Manoj Palat | 2020-08-15 17:29:33 +0000 |
---|---|---|
committer | Manoj Palat | 2020-08-15 17:29:33 +0000 |
commit | 9ceeac56c5b6cbdf7d200620db098a097d629e82 (patch) | |
tree | 327e9c5aeb4627b1dbd353a9db62fe716b6be620 | |
parent | e5e0eecd92d4e497573f4df8043c4ac92e394ad1 (diff) | |
download | eclipse.jdt.core-9ceeac56c5b6cbdf7d200620db098a097d629e82.tar.gz eclipse.jdt.core-9ceeac56c5b6cbdf7d200620db098a097d629e82.tar.xz eclipse.jdt.core-9ceeac56c5b6cbdf7d200620db098a097d629e82.zip |
Bug 565787 - Invalid code generated for records -I20200816-0600I20200815-1800
java.lang.invoke.LambdaConversionException at runtime
Change-Id: Id337da18abaf0af53a9f4b4ac9bf606868d30227
Signed-off-by: Manoj Palat <manpalat@in.ibm.com>
5 files changed, 193 insertions, 188 deletions
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 6de0a9b851..8aa63ad5af 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 @@ -3922,4 +3922,21 @@ public void testBug565830_01() { }, "private final int X$1Bar.x"); } +public void testBug565787_01() { + runConformTest( + new String[] { + "X.java", + "public record X(String s) {\n"+ + " public X {\n"+ + " s.codePoints()\n"+ + " .forEach(cp -> System.out.println((java.util.function.Predicate<String>) \"\"::equals));\n"+ + " }\n"+ + " public static void main(String[] args) {\n"+ + " X a = new X(\"\");\n"+ + " a.equals(a);\n"+ + " }\n"+ + "}", + }, + ""); +} }
\ 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 974f01248a..3f728a020a 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 @@ -160,8 +160,7 @@ public class ClassFile implements TypeConstants, TypeIds { // that collection contains all the remaining bytes of the .class file public int headerOffset; public Map<TypeBinding, Boolean> innerClassesBindings; - public List bootstrapMethods = null; - public List<TypeBinding> recordBootstrapMethods = null; + public List<ASTNode> bootstrapMethods = null; public int methodCount; public int methodCountOffset; // pool managment @@ -177,6 +176,9 @@ public class ClassFile implements TypeConstants, TypeIds { public Set visitedTypes; + private int indexForMetaFactory = 0; + private int indexForAltMetaFactory = 0; + private int indexForObjectMethodBootStrap = 0; public static final int INITIAL_CONTENTS_SIZE = 400; public static final int INITIAL_HEADER_SIZE = 1500; public static final int INNER_CLASSES_SIZE = 5; @@ -423,9 +425,8 @@ public class ClassFile implements TypeConstants, TypeIds { attributesNumber += generateHierarchyInconsistentAttribute(); } // Functional expression, lambda bootstrap methods and record bootstrap methods - if ((this.bootstrapMethods != null && !this.bootstrapMethods.isEmpty()) || - (this.recordBootstrapMethods != null && !this.recordBootstrapMethods.isEmpty())) { - attributesNumber += generateBootstrapMethods(this.bootstrapMethods, this.recordBootstrapMethods); + if (this.bootstrapMethods != null && !this.bootstrapMethods.isEmpty()) { + attributesNumber += generateBootstrapMethods(this.bootstrapMethods); } // Inner class attribute int numberOfInnerClasses = this.innerClassesBindings == null ? 0 : this.innerClassesBindings.size(); @@ -1078,7 +1079,7 @@ public class ClassFile implements TypeConstants, TypeIds { * - default abstract methods * - lambda methods. */ - public void addSpecialMethods() { + public void addSpecialMethods(TypeDeclaration typeDecl) { // add all methods (default abstract methods and synthetic) @@ -1165,7 +1166,7 @@ public class ClassFile implements TypeConstants, TypeIds { case SyntheticMethodBinding.RecordOverrideEquals: case SyntheticMethodBinding.RecordOverrideHashCode: case SyntheticMethodBinding.RecordOverrideToString: - addSyntheticRecordOverrideMethods(syntheticMethod, syntheticMethod.purpose); + addSyntheticRecordOverrideMethods(typeDecl, syntheticMethod, syntheticMethod.purpose); break; } } @@ -1197,13 +1198,12 @@ public class ClassFile implements TypeConstants, TypeIds { } } - private void addSyntheticRecordOverrideMethods(SyntheticMethodBinding methodBinding, int purpose) { - if (this.recordBootstrapMethods == null) - this.recordBootstrapMethods = new ArrayList<>(3); - if (!this.recordBootstrapMethods.contains(methodBinding.declaringClass)) - this.recordBootstrapMethods.add(methodBinding.declaringClass); - int index = this.bootstrapMethods != null ? this.bootstrapMethods.size() + - this.recordBootstrapMethods.size() - 1 : 0; + private void addSyntheticRecordOverrideMethods(TypeDeclaration typeDecl, SyntheticMethodBinding methodBinding, int purpose) { + if (this.bootstrapMethods == null) + this.bootstrapMethods = new ArrayList<>(3); + if (!this.bootstrapMethods.contains(typeDecl)) + this.bootstrapMethods.add(typeDecl); + int index = this.bootstrapMethods.indexOf(typeDecl); generateMethodInfoHeader(methodBinding); int methodAttributeOffset = this.contentsOffset; // this will add exception attribute, synthetic attribute, deprecated attribute,... @@ -3576,7 +3576,7 @@ public class ClassFile implements TypeConstants, TypeIds { return 1; } - private int generateBootstrapMethods(List functionalExpressionList, List<TypeBinding> recordBootstrapMethods2) { + private int generateBootstrapMethods(List<ASTNode> bootStrapMethodsList) { /* See JVM spec 4.7.21 The BootstrapMethods attribute has the following format: BootstrapMethods_attribute { @@ -3594,9 +3594,7 @@ public class ClassFile implements TypeConstants, TypeIds { if (methodHandlesLookup == null) return 0; // skip bootstrap section, class path problem already reported, just avoid NPE. recordInnerClasses(methodHandlesLookup); // Should be done, it's what javac does also - int nfunctionalExpressions = functionalExpressionList != null ? functionalExpressionList.size() : 0; - int nRecordBootStraps = recordBootstrapMethods2 != null ? recordBootstrapMethods2.size() : 0; - int numberOfBootstraps = nfunctionalExpressions + nRecordBootStraps; + int numberOfBootstraps = bootStrapMethodsList != null ? bootStrapMethodsList.size() : 0; int localContentsOffset = this.contentsOffset; // Generate the boot strap attribute - since we are only making lambdas and // functional expressions, we know the size ahead of time - this less general @@ -3619,12 +3617,14 @@ public class ClassFile implements TypeConstants, TypeIds { this.contents[localContentsOffset++] = (byte) (numberOfBootstraps >> 8); this.contents[localContentsOffset++] = (byte) numberOfBootstraps; - if (nfunctionalExpressions > 0) - localContentsOffset = generateLambdaMetaFactoryBootStrapMethods(functionalExpressionList, - localContentsOffset, contentsEntries); - if (nRecordBootStraps > 0) - localContentsOffset = generateObjectMethodsBootStrapMethods(recordBootstrapMethods2, localContentsOffset, - contentsEntries); + for (int i = 0; i < numberOfBootstraps; i++) { + Object o = this.bootstrapMethods.get(i); + if (o instanceof FunctionalExpression) { + localContentsOffset = addBootStrapLambdaEntry(localContentsOffset, (FunctionalExpression) o); + } else if (o instanceof TypeDeclaration) { + localContentsOffset = addBootStrapRecordEntry(localContentsOffset, (TypeDeclaration) o); + } + } int attributeLength = localContentsOffset - attributeLengthPosition - 4; this.contents[attributeLengthPosition++] = (byte) (attributeLength >> 24); @@ -3635,184 +3635,173 @@ public class ClassFile implements TypeConstants, TypeIds { return 1; } - private int generateLambdaMetaFactoryBootStrapMethods(List functionalExpressionList, - int localContentsOffset, final int contentsEntries) { - ReferenceBinding javaLangInvokeLambdaMetafactory = this.referenceBinding.scope.getJavaLangInvokeLambdaMetafactory(); - int numberOfBootstraps = functionalExpressionList.size(); + private int addBootStrapLambdaEntry(int localContentsOffset, FunctionalExpression functional) { + MethodBinding [] bridges = functional.getRequiredBridges(); + TypeBinding[] markerInterfaces = null; + final int contentsEntries = 10; + if ((functional instanceof LambdaExpression + && (((markerInterfaces = ((LambdaExpression) functional).getMarkerInterfaces()) != null)) + || bridges != null) || functional.isSerializable) { + // may need even more space + int extraSpace = 2; // at least 2 more than when the normal metafactory is used, for the bitflags entry + if (markerInterfaces != null) { + // 2 for the marker interface list size then 2 per marker interface index + extraSpace += (2 + 2 * markerInterfaces.length); + } + if (bridges != null) { + // 2 for bridge count then 2 per bridge method type. + extraSpace += (2 + 2 * bridges.length); + } + if (extraSpace + contentsEntries + localContentsOffset >= this.contents.length) { + resizeContents(extraSpace + contentsEntries); + } - // Depending on the complexity of the expression it may be necessary to use the altMetafactory() rather than the metafactory() - int indexForMetaFactory = 0; - int indexForAltMetaFactory = 0; + if (this.indexForAltMetaFactory == 0) { + ReferenceBinding javaLangInvokeLambdaMetafactory = this.referenceBinding.scope.getJavaLangInvokeLambdaMetafactory(); + this.indexForAltMetaFactory = + this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, + ConstantPool.ALTMETAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_ALTMETAFACTORY_SIGNATURE, false); + } + this.contents[localContentsOffset++] = (byte) (this.indexForAltMetaFactory >> 8); + this.contents[localContentsOffset++] = (byte) this.indexForAltMetaFactory; - for (int i = 0; i < numberOfBootstraps; i++) { - FunctionalExpression functional = (FunctionalExpression) functionalExpressionList.get(i); - MethodBinding [] bridges = functional.getRequiredBridges(); - TypeBinding[] markerInterfaces = null; - if ((functional instanceof LambdaExpression - && (((markerInterfaces = ((LambdaExpression) functional).getMarkerInterfaces()) != null)) - || bridges != null) || functional.isSerializable) { - // may need even more space - int extraSpace = 2; // at least 2 more than when the normal metafactory is used, for the bitflags entry - if (markerInterfaces != null) { - // 2 for the marker interface list size then 2 per marker interface index - extraSpace += (2 + 2 * markerInterfaces.length); - } - if (bridges != null) { - // 2 for bridge count then 2 per bridge method type. - extraSpace += (2 + 2 * bridges.length); - } - if (extraSpace + contentsEntries + localContentsOffset >= this.contents.length) { - resizeContents(extraSpace + contentsEntries); - } + // u2 num_bootstrap_arguments + this.contents[localContentsOffset++] = 0; + this.contents[localContentsOffset++] = (byte) (4 + (markerInterfaces==null?0:1+markerInterfaces.length) + + (bridges == null ? 0 : 1 + bridges.length)); - if (indexForAltMetaFactory == 0) { - indexForAltMetaFactory = - this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, - ConstantPool.ALTMETAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_ALTMETAFACTORY_SIGNATURE, false); - } - this.contents[localContentsOffset++] = (byte) (indexForAltMetaFactory >> 8); - this.contents[localContentsOffset++] = (byte) indexForAltMetaFactory; + int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature()); + this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8); + this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex; - // u2 num_bootstrap_arguments - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = (byte) (4 + (markerInterfaces==null?0:1+markerInterfaces.length) + - (bridges == null ? 0 : 1 + bridges.length)); + int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below. + this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8); + this.contents[localContentsOffset++] = (byte) methodHandleIndex; - int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature()); - this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex; + char [] instantiatedSignature = functional.descriptor.signature(); + int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature); + this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8); + this.contents[localContentsOffset++] = (byte) methodTypeIndex; - int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below. - this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodHandleIndex; + int bitflags = 0; + if (functional.isSerializable) { + bitflags |= ClassFileConstants.FLAG_SERIALIZABLE; + } + if (markerInterfaces!=null) { + bitflags |= ClassFileConstants.FLAG_MARKERS; + } + if (bridges != null) { + bitflags |= ClassFileConstants.FLAG_BRIDGES; + } + int indexForBitflags = this.constantPool.literalIndex(bitflags); - char [] instantiatedSignature = functional.descriptor.signature(); - int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature); - this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodTypeIndex; + this.contents[localContentsOffset++] = (byte)(indexForBitflags>>8); + this.contents[localContentsOffset++] = (byte)(indexForBitflags); - int bitflags = 0; - if (functional.isSerializable) { - bitflags |= ClassFileConstants.FLAG_SERIALIZABLE; - } - if (markerInterfaces!=null) { - bitflags |= ClassFileConstants.FLAG_MARKERS; - } - if (bridges != null) { - bitflags |= ClassFileConstants.FLAG_BRIDGES; - } - int indexForBitflags = this.constantPool.literalIndex(bitflags); - - this.contents[localContentsOffset++] = (byte)(indexForBitflags>>8); - this.contents[localContentsOffset++] = (byte)(indexForBitflags); - - if (markerInterfaces != null) { - int markerInterfaceCountIndex = this.constantPool.literalIndex(markerInterfaces.length); - this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex>>8); - this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex); - for (int m = 0, maxm = markerInterfaces.length; m < maxm; m++) { - int classTypeIndex = this.constantPool.literalIndexForType(markerInterfaces[m]); - this.contents[localContentsOffset++] = (byte)(classTypeIndex>>8); - this.contents[localContentsOffset++] = (byte)(classTypeIndex); - } - } - if (bridges != null) { - int bridgeCountIndex = this.constantPool.literalIndex(bridges.length); - this.contents[localContentsOffset++] = (byte) (bridgeCountIndex >> 8); - this.contents[localContentsOffset++] = (byte) (bridgeCountIndex); - for (int m = 0, maxm = bridges.length; m < maxm; m++) { - char [] bridgeSignature = bridges[m].signature(); - int bridgeMethodTypeIndex = this.constantPool.literalIndexForMethodType(bridgeSignature); - this.contents[localContentsOffset++] = (byte) (bridgeMethodTypeIndex >> 8); - this.contents[localContentsOffset++] = (byte) bridgeMethodTypeIndex; - } - } - } else { - if (contentsEntries + localContentsOffset >= this.contents.length) { - resizeContents(contentsEntries); + if (markerInterfaces != null) { + int markerInterfaceCountIndex = this.constantPool.literalIndex(markerInterfaces.length); + this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex>>8); + this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex); + for (int m = 0, maxm = markerInterfaces.length; m < maxm; m++) { + int classTypeIndex = this.constantPool.literalIndexForType(markerInterfaces[m]); + this.contents[localContentsOffset++] = (byte)(classTypeIndex>>8); + this.contents[localContentsOffset++] = (byte)(classTypeIndex); } - if (indexForMetaFactory == 0) { - indexForMetaFactory = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, - ConstantPool.METAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_METAFACTORY_SIGNATURE, false); + } + if (bridges != null) { + int bridgeCountIndex = this.constantPool.literalIndex(bridges.length); + this.contents[localContentsOffset++] = (byte) (bridgeCountIndex >> 8); + this.contents[localContentsOffset++] = (byte) (bridgeCountIndex); + for (int m = 0, maxm = bridges.length; m < maxm; m++) { + char [] bridgeSignature = bridges[m].signature(); + int bridgeMethodTypeIndex = this.constantPool.literalIndexForMethodType(bridgeSignature); + this.contents[localContentsOffset++] = (byte) (bridgeMethodTypeIndex >> 8); + this.contents[localContentsOffset++] = (byte) bridgeMethodTypeIndex; } - this.contents[localContentsOffset++] = (byte) (indexForMetaFactory >> 8); - this.contents[localContentsOffset++] = (byte) indexForMetaFactory; + } + } else { + if (contentsEntries + localContentsOffset >= this.contents.length) { + resizeContents(contentsEntries); + } + if (this.indexForMetaFactory == 0) { + ReferenceBinding javaLangInvokeLambdaMetafactory = this.referenceBinding.scope.getJavaLangInvokeLambdaMetafactory(); + this.indexForMetaFactory = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, + ConstantPool.METAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_METAFACTORY_SIGNATURE, false); + } + this.contents[localContentsOffset++] = (byte) (this.indexForMetaFactory >> 8); + this.contents[localContentsOffset++] = (byte) this.indexForMetaFactory; - // u2 num_bootstrap_arguments - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = (byte) 3; + // u2 num_bootstrap_arguments + this.contents[localContentsOffset++] = 0; + this.contents[localContentsOffset++] = (byte) 3; - int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature()); - this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex; + int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature()); + this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8); + this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex; - int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding instanceof PolymorphicMethodBinding ? functional.binding : functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below. - this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodHandleIndex; + int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding instanceof PolymorphicMethodBinding ? functional.binding : functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below. + this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8); + this.contents[localContentsOffset++] = (byte) methodHandleIndex; - char [] instantiatedSignature = functional.descriptor.signature(); - int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature); - this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodTypeIndex; - } + char [] instantiatedSignature = functional.descriptor.signature(); + int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature); + this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8); + this.contents[localContentsOffset++] = (byte) methodTypeIndex; } return localContentsOffset; } - private int generateObjectMethodsBootStrapMethods(List<TypeBinding> recordList, - int localContentsOffset, final int contentsEntries) { - ReferenceBinding javaLangRuntimeObjectMethods = this.referenceBinding.scope.getJavaLangRuntimeObjectMethods(); - int numberOfBootstraps = recordList.size(); - int indexForObjectMethodBootStrap = 0; - for (int i = 0; i < numberOfBootstraps; i++) { - if (contentsEntries + localContentsOffset >= this.contents.length) { - resizeContents(contentsEntries); - } - if (indexForObjectMethodBootStrap == 0) { - indexForObjectMethodBootStrap = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangRuntimeObjectMethods, - ConstantPool.BOOTSTRAP, ConstantPool.JAVA_LANG_RUNTIME_OBJECTMETHOD_BOOTSTRAP_SIGNATURE, false); - } - this.contents[localContentsOffset++] = (byte) (indexForObjectMethodBootStrap >> 8); - this.contents[localContentsOffset++] = (byte) indexForObjectMethodBootStrap; - // u2 num_bootstrap_arguments - int numArgsLocation = localContentsOffset; - localContentsOffset += 2; + private int addBootStrapRecordEntry(int localContentsOffset, TypeDeclaration typeDecl) { + TypeBinding type = typeDecl.binding; + assert type.isRecord(); // sanity check + final int contentsEntries = 10; + if (contentsEntries + localContentsOffset >= this.contents.length) { + resizeContents(contentsEntries); + } + if (this.indexForObjectMethodBootStrap == 0) { + ReferenceBinding javaLangRuntimeObjectMethods = this.referenceBinding.scope.getJavaLangRuntimeObjectMethods(); + this.indexForObjectMethodBootStrap = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangRuntimeObjectMethods, + ConstantPool.BOOTSTRAP, ConstantPool.JAVA_LANG_RUNTIME_OBJECTMETHOD_BOOTSTRAP_SIGNATURE, false); + } + this.contents[localContentsOffset++] = (byte) (this.indexForObjectMethodBootStrap >> 8); + this.contents[localContentsOffset++] = (byte) this.indexForObjectMethodBootStrap; - TypeBinding type = recordList.get(i); - assert type.isRecord(); // sanity check - char[] recordName = type.constantPoolName(); - int recordIndex = this.constantPool.literalIndexForType(recordName); - this.contents[localContentsOffset++] = (byte) (recordIndex >> 8); - this.contents[localContentsOffset++] = (byte) recordIndex; + // u2 num_bootstrap_arguments + int numArgsLocation = localContentsOffset; + localContentsOffset += 2; - assert type instanceof SourceTypeBinding; - SourceTypeBinding sourceType = (SourceTypeBinding) type; - FieldBinding[] recordComponents = sourceType.getImplicitComponentFields(); + char[] recordName = type.constantPoolName(); + int recordIndex = this.constantPool.literalIndexForType(recordName); + this.contents[localContentsOffset++] = (byte) (recordIndex >> 8); + this.contents[localContentsOffset++] = (byte) recordIndex; - int numArgs = 2 + recordComponents.length; - this.contents[numArgsLocation++] = (byte) (numArgs >> 8); - this.contents[numArgsLocation] = (byte) numArgs; + assert type instanceof SourceTypeBinding; + SourceTypeBinding sourceType = (SourceTypeBinding) type; + FieldBinding[] recordComponents = sourceType.getImplicitComponentFields(); - String names = - Arrays.stream(recordComponents) - .map(f -> new String(f.name)) - .reduce((s1, s2) -> { return s1 + ";" + s2;}) //$NON-NLS-1$ - .orElse(Util.EMPTY_STRING); - int namesIndex = this.constantPool.literalIndex(names); - this.contents[localContentsOffset++] = (byte) (namesIndex >> 8); - this.contents[localContentsOffset++] = (byte) namesIndex; + int numArgs = 2 + recordComponents.length; + this.contents[numArgsLocation++] = (byte) (numArgs >> 8); + this.contents[numArgsLocation] = (byte) numArgs; - if (recordComponents.length * 2 + localContentsOffset >= this.contents.length) { - resizeContents(recordComponents.length * 2); - } - for (FieldBinding field : recordComponents) { - int methodHandleIndex = this.constantPool.literalIndexForMethodHandleFieldRef( - ClassFileConstants.MethodHandleRefKindGetField, - recordName, field.name, field.type.signature()); + String names = + Arrays.stream(recordComponents) + .map(f -> new String(f.name)) + .reduce((s1, s2) -> { return s1 + ";" + s2;}) //$NON-NLS-1$ + .orElse(Util.EMPTY_STRING); + int namesIndex = this.constantPool.literalIndex(names); + this.contents[localContentsOffset++] = (byte) (namesIndex >> 8); + this.contents[localContentsOffset++] = (byte) namesIndex; - this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodHandleIndex; - } + if (recordComponents.length * 2 + localContentsOffset >= this.contents.length) { + resizeContents(recordComponents.length * 2); + } + for (FieldBinding field : recordComponents) { + 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; } @@ -6029,10 +6018,13 @@ public class ClassFile implements TypeConstants, TypeIds { } if (expression instanceof ReferenceExpression) { for (int i = 0; i < this.bootstrapMethods.size(); i++) { - FunctionalExpression fexp = (FunctionalExpression) this.bootstrapMethods.get(i); - if (fexp.binding == expression.binding - && TypeBinding.equalsEquals(fexp.expectedType(), expression.expectedType())) - return expression.bootstrapMethodNumber = i; + ASTNode node = this.bootstrapMethods.get(i); + if (node instanceof FunctionalExpression) { + FunctionalExpression fexp = (FunctionalExpression) node; + if (fexp.binding == expression.binding + && TypeBinding.equalsEquals(fexp.expectedType(), expression.expectedType())) + return expression.bootstrapMethodNumber = i; + } } } this.bootstrapMethods.add(expression); @@ -6081,9 +6073,6 @@ public class ClassFile implements TypeConstants, TypeIds { if (this.bootstrapMethods != null) { this.bootstrapMethods.clear(); } - if (this.recordBootstrapMethods != null) { - this.recordBootstrapMethods.clear(); - } this.missingTypes = null; this.visitedTypes = null; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java index bfc5cb05fe..8beee5a001 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java @@ -174,7 +174,6 @@ public void cleanUp() { classFile.referenceBinding = null; classFile.innerClassesBindings = null; classFile.bootstrapMethods = null; - classFile.recordBootstrapMethods = null; classFile.missingTypes = null; classFile.visitedTypes = null; } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java index ba892531da..e6e22c8815 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java @@ -748,7 +748,7 @@ public void generateCode(ClassFile enclosingClassFile) { } } // generate all synthetic and abstract methods - classFile.addSpecialMethods(); + classFile.addSpecialMethods(this); if (this.ignoreFurtherInvestigation) { // trigger problem type generation for code gen errors throw new AbortType(this.scope.referenceCompilationUnit().compilationResult, null); diff --git a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java index 330d96b226..8510532dac 100644 --- a/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java +++ b/org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java @@ -76,7 +76,7 @@ public void generateCode(ClassFile enclosingClassFile) { } // generate all methods - classFile.addSpecialMethods(); + classFile.addSpecialMethods(this); if (this.ignoreFurtherInvestigation){ // trigger problem type generation for code gen errors throw new AbortType(this.scope.referenceCompilationUnit().compilationResult, null); |