Skip to content

Commit

Permalink
When is ReferenceBinding.hashCode() used outside HashMap?
Browse files Browse the repository at this point in the history
  • Loading branch information
EcljpseB0T committed Dec 6, 2024
1 parent 11bf464 commit 42a5bc4
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.StatementWithFinallyBlock;
import org.eclipse.jdt.internal.compiler.ast.TryStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.UnionTypeReference;
import org.eclipse.jdt.internal.compiler.codegen.ObjectCache;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.CatchParameterBinding;
import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
Expand All @@ -52,7 +53,7 @@ public class ExceptionHandlingFlowContext extends FlowContext {
int[] isNeeded;
// WARNING: This is an array that maps to catch blocks, not caught exceptions (which could be more than catch blocks in a multi-catch block)
UnconditionalFlowInfo[] initsOnExceptions;
ObjectCache indexes = new ObjectCache();
Map<ReferenceBinding, Integer> indexes = new HashMap<>();
boolean isMethodContext;

public UnconditionalFlowInfo initsOnReturn;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.classfmt.AnnotationInfo;
Expand All @@ -66,7 +68,6 @@
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.Util;

/*
Expand Down Expand Up @@ -104,7 +105,7 @@ public class BinaryTypeBinding extends ReferenceBinding {
// For the link with the principle structure
protected LookupEnvironment environment;

protected SimpleLookupTable storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder
protected Map<Binding, AnnotationHolder> storedAnnotations = null; // keys are this ReferenceBinding & its fields and methods, value is an AnnotationHolder

private ReferenceBinding containerAnnotationType;
int defaultNullness = 0;
Expand Down Expand Up @@ -1976,15 +1977,15 @@ public void tagAsHavingDefectiveContainerType() {
}

@Override
SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) {
Map<Binding, AnnotationHolder> storedAnnotations(boolean forceInitialize, boolean forceStore) {

if (!isPrototype())
return this.prototype.storedAnnotations(forceInitialize, forceStore);

if (forceInitialize && this.storedAnnotations == null) {
if (!this.environment.globalOptions.storeAnnotations && !forceStore)
return null; // not supported during this compile
this.storedAnnotations = new SimpleLookupTable(3);
this.storedAnnotations = new HashMap<>();
}
return this.storedAnnotations;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ public class LookupEnvironment implements ProblemReasons, TypeConstants {
private CompleteTypeBindingsSteps stepCompleted = CompleteTypeBindingsSteps.NONE; // ROOT_ONLY
public ITypeRequestor typeRequestor; // SHARED

private SimpleLookupTable uniqueParameterizedGenericMethodBindings;
private Map<MethodBinding, ParameterizedGenericMethodBinding[]> uniqueParameterizedGenericMethodBindings;

// key is a string with the method selector value is an array of method bindings
private SimpleLookupTable uniquePolymorphicMethodBindings;
private SimpleLookupTable uniqueGetClassMethodBinding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300734
private Map<TypeBinding, ParameterizedMethodBinding> uniqueGetClassMethodBinding; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=300734

boolean useModuleSystem; // true when compliance >= 9 and nameEnvironment is module aware
// key is a string with the module name value is a module binding
Expand Down Expand Up @@ -215,7 +215,7 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOpt
this.defaultImports = null;
this.nameEnvironment = nameEnvironment;
this.knownPackages = new HashtableOfPackage();
this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3);
this.uniqueParameterizedGenericMethodBindings = new HashMap<>();
this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3);
this.missingTypes = null;
this.accessRestrictions = new HashMap(3);
Expand All @@ -240,7 +240,7 @@ public LookupEnvironment(ITypeRequestor typeRequestor, CompilerOptions globalOpt
this.defaultImports = null;
this.nameEnvironment = rootEnv.nameEnvironment;
this.knownPackages = new HashtableOfPackage();
this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3);
this.uniqueParameterizedGenericMethodBindings = new HashMap<>();
this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3);
this.missingTypes = null;
this.accessRestrictions = new HashMap(3);
Expand Down Expand Up @@ -1194,7 +1194,7 @@ public PlainPackageBinding createPlainPackage(char[][] compoundName) {

public ParameterizedGenericMethodBinding createParameterizedGenericMethod(MethodBinding genericMethod, RawTypeBinding rawType) {
// cached info is array of already created parameterized types for this type
ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[])this.uniqueParameterizedGenericMethodBindings.get(genericMethod);
ParameterizedGenericMethodBinding[] cachedInfo = this.uniqueParameterizedGenericMethodBindings.get(genericMethod);
boolean needToGrow = false;
int index = 0;
if (cachedInfo != null){
Expand Down Expand Up @@ -1234,7 +1234,7 @@ public ParameterizedGenericMethodBinding createParameterizedGenericMethod(Method
boolean inferredWithUncheckedConversion, boolean hasReturnProblem, TypeBinding targetType)
{
// cached info is array of already created parameterized types for this type
ParameterizedGenericMethodBinding[] cachedInfo = (ParameterizedGenericMethodBinding[])this.uniqueParameterizedGenericMethodBindings.get(genericMethod);
ParameterizedGenericMethodBinding[] cachedInfo = this.uniqueParameterizedGenericMethodBindings.get(genericMethod);
int argLength = typeArguments == null ? 0: typeArguments.length;
boolean needToGrow = false;
int index = 0;
Expand Down Expand Up @@ -1382,9 +1382,9 @@ public ParameterizedMethodBinding createGetClassMethod(TypeBinding receiverType,
// see if we have already cached this method for the given receiver type.
ParameterizedMethodBinding retVal = null;
if (this.uniqueGetClassMethodBinding == null) {
this.uniqueGetClassMethodBinding = new SimpleLookupTable(3);
this.uniqueGetClassMethodBinding = new HashMap<>();
} else {
retVal = (ParameterizedMethodBinding)this.uniqueGetClassMethodBinding.get(receiverType);
retVal = this.uniqueGetClassMethodBinding.get(receiverType);
}
if (retVal == null) {
retVal = ParameterizedMethodBinding.instantiateGetClass(receiverType, originalMethod, scope);
Expand Down Expand Up @@ -2322,7 +2322,7 @@ public void reset() {
this.verifier = null;

// NOTE: remember to fix #updateCaches(...) when adding unique binding caches
this.uniqueParameterizedGenericMethodBindings = new SimpleLookupTable(3);
this.uniqueParameterizedGenericMethodBindings = new HashMap<>();
this.uniquePolymorphicMethodBindings = new SimpleLookupTable(3);
this.uniqueGetClassMethodBinding = null;
this.missingTypes = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.compiler.util.Sorting;

@SuppressWarnings({"rawtypes", "unchecked"})
Expand Down Expand Up @@ -295,16 +294,16 @@ void checkForMissingHashCodeMethod() {
void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
if (superInterfaces == Binding.NO_SUPERINTERFACES) return;

SimpleSet interfacesToCheck = new SimpleSet(superInterfaces.length);
SimpleSet redundantInterfaces = null; // bark but once.
Set<ReferenceBinding> interfacesToCheck = new HashSet<>(superInterfaces.length);
Set<ReferenceBinding> redundantInterfaces = null; // bark but once.
for (int i = 0, l = superInterfaces.length; i < l; i++) {
ReferenceBinding toCheck = superInterfaces[i];
for (int j = 0; j < l; j++) {
ReferenceBinding implementedInterface = superInterfaces[j];
if (i != j && toCheck.implementsInterface(implementedInterface, true)) {
if (redundantInterfaces == null) {
redundantInterfaces = new SimpleSet(3);
} else if (redundantInterfaces.includes(implementedInterface)) {
redundantInterfaces = new HashSet<>();
} else if (redundantInterfaces.contains(implementedInterface)) {
continue;
}
redundantInterfaces.add(implementedInterface);
Expand All @@ -321,16 +320,16 @@ void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBind
}

ReferenceBinding[] itsInterfaces = null;
SimpleSet inheritedInterfaces = new SimpleSet(5);
Set<ReferenceBinding> inheritedInterfaces = new HashSet<>();
ReferenceBinding superType = superclass;
while (superType != null && superType.isValidBinding()) {
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) {
for (ReferenceBinding inheritedInterface : itsInterfaces) {
if (!inheritedInterfaces.includes(inheritedInterface) && inheritedInterface.isValidBinding()) {
if (interfacesToCheck.includes(inheritedInterface)) {
if (!inheritedInterfaces.contains(inheritedInterface) && inheritedInterface.isValidBinding()) {
if (interfacesToCheck.contains(inheritedInterface)) {
if (redundantInterfaces == null) {
redundantInterfaces = new SimpleSet(3);
} else if (redundantInterfaces.includes(inheritedInterface)) {
redundantInterfaces = new HashSet<>();
} else if (redundantInterfaces.contains(inheritedInterface)) {
continue;
}
redundantInterfaces.add(inheritedInterface);
Expand All @@ -350,10 +349,9 @@ void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBind
superType = superType.superclass();
}

int nextPosition = inheritedInterfaces.elementSize;
int nextPosition = inheritedInterfaces.size();
if (nextPosition == 0) return;
ReferenceBinding[] interfacesToVisit = new ReferenceBinding[nextPosition];
inheritedInterfaces.asArray(interfacesToVisit);
ReferenceBinding[] interfacesToVisit = inheritedInterfaces.toArray(ReferenceBinding[]::new);
for (int i = 0; i < nextPosition; i++) {
superType = interfacesToVisit[i];
if ((itsInterfaces = superType.superInterfaces()) != Binding.NO_SUPERINTERFACES) {
Expand All @@ -362,11 +360,11 @@ void checkForRedundantSuperinterfaces(ReferenceBinding superclass, ReferenceBind
System.arraycopy(interfacesToVisit, 0, interfacesToVisit = new ReferenceBinding[nextPosition + itsLength + 5], 0, nextPosition);
for (int a = 0; a < itsLength; a++) {
ReferenceBinding inheritedInterface = itsInterfaces[a];
if (!inheritedInterfaces.includes(inheritedInterface) && inheritedInterface.isValidBinding()) {
if (interfacesToCheck.includes(inheritedInterface)) {
if (!inheritedInterfaces.contains(inheritedInterface) && inheritedInterface.isValidBinding()) {
if (interfacesToCheck.contains(inheritedInterface)) {
if (redundantInterfaces == null) {
redundantInterfaces = new SimpleSet(3);
} else if (redundantInterfaces.includes(inheritedInterface)) {
redundantInterfaces = new HashSet<>();
} else if (redundantInterfaces.contains(inheritedInterface)) {
continue;
}
redundantInterfaces.add(inheritedInterface);
Expand Down Expand Up @@ -632,12 +630,12 @@ void computeInheritedMethods(ReferenceBinding superclass, ReferenceBinding[] sup
superInterfaces = Sorting.sortTypes(superInterfaces);
}

SimpleSet skip = findSuperinterfaceCollisions(superclass, superInterfaces);
Set<ReferenceBinding> skip = findSuperinterfaceCollisions(superclass, superInterfaces);
int len = superInterfaces.length;
for (int i = len-1; i >= 0; i--) {
superType = superInterfaces[i];
if (superType.isValidBinding()) {
if (skip != null && skip.includes(superType)) continue;
if (skip != null && skip.contains(superType)) continue;

MethodBinding[] methods = superType.unResolvedMethods();
nextMethod : for (int m = methods.length; --m >= 0;) { // Interface methods are all abstract public
Expand Down Expand Up @@ -792,7 +790,7 @@ public boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedM
public static boolean doesMethodOverride(MethodBinding method, MethodBinding inheritedMethod, LookupEnvironment environment) {
return couldMethodOverride(method, inheritedMethod) && areMethodsCompatible(method, inheritedMethod, environment);
}
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
Set<ReferenceBinding> findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
return null; // noop in 1.4
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@


import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
Expand All @@ -47,7 +49,6 @@
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.SimpleSet;
import org.eclipse.jdt.internal.compiler.util.Sorting;

class MethodVerifier15 extends MethodVerifier {
Expand Down Expand Up @@ -864,7 +865,7 @@ boolean doTypeVariablesClash(MethodBinding one, MethodBinding substituteTwo) {
return one.typeVariables != Binding.NO_TYPE_VARIABLES && !(substituteTwo instanceof ParameterizedGenericMethodBinding);
}
@Override
SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
Set<ReferenceBinding> findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBinding[] superInterfaces) {
ReferenceBinding[] interfacesToVisit = null;
int nextPosition = 0;
ReferenceBinding[] itsInterfaces = superInterfaces;
Expand Down Expand Up @@ -915,7 +916,7 @@ SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBin
}

if (!isInconsistent) return null; // hierarchy is consistent so no collisions are possible
SimpleSet copy = null;
Set<ReferenceBinding> copy = null;
for (int i = 0; i < nextPosition; i++) {
ReferenceBinding current = interfacesToVisit[i];
if (current.isValidBinding()) {
Expand All @@ -924,7 +925,7 @@ SimpleSet findSuperinterfaceCollisions(ReferenceBinding superclass, ReferenceBin
ReferenceBinding next = interfacesToVisit[j];
if (next.isValidBinding() && TypeBinding.equalsEquals(next.erasure(), erasure)) {
if (copy == null)
copy = new SimpleSet(nextPosition);
copy = new HashSet<>(nextPosition);
copy.add(interfacesToVisit[i]);
copy.add(interfacesToVisit[j]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
Expand All @@ -65,7 +67,6 @@
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.ReferenceContext;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;

/*
Not all fields defined by this type (& its subclasses) are initialized when it is created.
Expand All @@ -88,7 +89,7 @@ abstract public class ReferenceBinding extends TypeBinding {
char[] constantPoolName;
char[] signature;

private SimpleLookupTable compatibleCache;
private Map<TypeBinding, Boolean> compatibleCache;

int typeBits; // additional bits characterizing this type
protected MethodBinding [] singleAbstractMethod;
Expand Down Expand Up @@ -1206,6 +1207,17 @@ public TypeVariableBinding getTypeVariable(char[] variableName) {

@Override
public int hashCode() {
if (!StackWalker.
getInstance().
walk(stream -> stream.anyMatch(s -> "java.util.HashMap".equals(s.getClassName()) //$NON-NLS-1$
|| "java.util.concurrent.ConcurrentHashMap".equals(s.getClassName())))) //$NON-NLS-1$

{
RuntimeException e=new RuntimeException("called outside HashMap"); //$NON-NLS-1$
e.printStackTrace();
throw e;
}

// ensure ReferenceBindings hash to the same position as UnresolvedReferenceBindings so they can be replaced without rehashing
// ALL ReferenceBindings are unique when created so equals() is the same as ==
return (this.compoundName == null || this.compoundName.length == 0)
Expand Down Expand Up @@ -1450,7 +1462,7 @@ public boolean isCompatibleWith(TypeBinding otherType, /*@Nullable*/ Scope captu
return true;
Object result;
if (this.compatibleCache == null) {
this.compatibleCache = new SimpleLookupTable(3);
this.compatibleCache = new HashMap<>();
result = null;
} else {
result = this.compatibleCache.get(otherType); // [dbg reset] this.compatibleCache.put(otherType,null)
Expand Down Expand Up @@ -1901,8 +1913,8 @@ protected void appendNullAnnotation(StringBuilder nameBuffer, CompilerOptions op
}

public AnnotationHolder retrieveAnnotationHolder(Binding binding, boolean forceInitialization) {
SimpleLookupTable store = storedAnnotations(forceInitialization, false);
return store == null ? null : (AnnotationHolder) store.get(binding);
Map<Binding, AnnotationHolder> store = storedAnnotations(forceInitialization, false);
return store == null ? null : store.get(binding);
}

AnnotationBinding[] retrieveAnnotations(Binding binding) {
Expand Down Expand Up @@ -2067,11 +2079,11 @@ public TypeBinding downwardsProjection(Scope scope, TypeBinding[] mentionedTypeV

void storeAnnotationHolder(Binding binding, AnnotationHolder holder) {
if (holder == null) {
SimpleLookupTable store = storedAnnotations(false, false);
Map<Binding, AnnotationHolder> store = storedAnnotations(false, false);
if (store != null)
store.removeKey(binding);
store.remove(binding);
} else {
SimpleLookupTable store = storedAnnotations(true, false);
Map<Binding, AnnotationHolder> store = storedAnnotations(true, false);
if (store != null)
store.put(binding, holder);
}
Expand All @@ -2080,21 +2092,21 @@ void storeAnnotationHolder(Binding binding, AnnotationHolder holder) {
void storeAnnotations(Binding binding, AnnotationBinding[] annotations, boolean forceStore) {
AnnotationHolder holder = null;
if (annotations == null || annotations.length == 0) {
SimpleLookupTable store = storedAnnotations(false, forceStore);
Map<Binding, AnnotationHolder> store = storedAnnotations(false, forceStore);
if (store != null)
holder = (AnnotationHolder) store.get(binding);
holder = store.get(binding);
if (holder == null) return; // nothing to delete
} else {
SimpleLookupTable store = storedAnnotations(true, forceStore);
Map<Binding, AnnotationHolder> store = storedAnnotations(true, forceStore);
if (store == null) return; // not supported
holder = (AnnotationHolder) store.get(binding);
holder = store.get(binding);
if (holder == null)
holder = new AnnotationHolder();
}
storeAnnotationHolder(binding, holder.setAnnotations(annotations));
}

SimpleLookupTable storedAnnotations(boolean forceInitialize, boolean forceStore) {
Map<Binding, AnnotationHolder> storedAnnotations(boolean forceInitialize, boolean forceStore) {
return null; // overrride if interested in storing annotations for the receiver, its fields and methods
}

Expand Down
Loading

0 comments on commit 42a5bc4

Please sign in to comment.