Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorManoj Palat2020-08-15 17:29:33 +0000
committerManoj Palat2020-08-15 17:29:33 +0000
commit9ceeac56c5b6cbdf7d200620db098a097d629e82 (patch)
tree327e9c5aeb4627b1dbd353a9db62fe716b6be620
parente5e0eecd92d4e497573f4df8043c4ac92e394ad1 (diff)
downloadeclipse.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>
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java17
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java359
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java1
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java2
-rw-r--r--org.eclipse.jdt.core/eval/org/eclipse/jdt/internal/eval/CodeSnippetTypeDeclaration.java2
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);

Back to the top