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 c1bdc21
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 72 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 @@ -295,16 +295,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 +321,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 +350,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 +361,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
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
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
import org.eclipse.jdt.internal.compiler.util.ObjectVector;
import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
import org.eclipse.jdt.internal.compiler.util.SimpleSet;

@SuppressWarnings({ "rawtypes", "unchecked" })
Expand Down Expand Up @@ -4993,7 +4992,7 @@ && compilerOptions().isAnnotationBasedNullAnalysisEnabled
int mostSpecificLength = mostSpecificExceptions.length;
ReferenceBinding[] nextExceptions = getFilteredExceptions(next);
int nextLength = nextExceptions.length;
SimpleSet temp = new SimpleSet(mostSpecificLength);
Set<ReferenceBinding> temp = new HashSet<>(mostSpecificLength);
boolean changed = false;
nextException : for (int t = 0; t < mostSpecificLength; t++) {
ReferenceBinding exception = mostSpecificExceptions[t];
Expand All @@ -5012,8 +5011,7 @@ && compilerOptions().isAnnotationBasedNullAnalysisEnabled
}
}
if (changed) {
mostSpecificExceptions = temp.elementSize == 0 ? Binding.NO_EXCEPTIONS : new ReferenceBinding[temp.elementSize];
temp.asArray(mostSpecificExceptions);
mostSpecificExceptions = temp.toArray(ReferenceBinding[]::new);
}
}
}
Expand Down Expand Up @@ -5395,7 +5393,7 @@ public MethodBinding getStaticFactory (ParameterizedTypeBinding allocationType,
MethodBinding targetMethod = isInterface ? new MethodBinding(method.original(), genericType) : method.original();
MethodBinding staticFactory = new SyntheticFactoryMethodBinding(targetMethod, environment, originalEnclosingType);
staticFactory.typeVariables = new TypeVariableBinding[factoryArity];
final SimpleLookupTable map = new SimpleLookupTable(factoryArity);
Map<TypeBinding, TypeVariableBinding> map = new HashMap<>(factoryArity);

// Rename each type variable T of the type to T' or T'' or T''' based on the enclosing level to avoid a clash.
String prime = ""; //$NON-NLS-1$
Expand Down Expand Up @@ -5430,15 +5428,15 @@ public boolean isRawSubstitution() {
}
@Override
public TypeBinding substitute(TypeVariableBinding typeVariable) {
TypeBinding retVal = (TypeBinding) map.get(typeVariable.unannotated());
TypeBinding retVal = map.get(typeVariable.unannotated());
return retVal == null ? typeVariable : typeVariable.hasTypeAnnotations() ? environment().createAnnotatedType(retVal, typeVariable.getTypeAnnotations()) : retVal;
}
};

// initialize new variable bounds
for (int j = 0; j < factoryArity; j++) {
TypeVariableBinding originalVariable = j < classTypeVariablesArity ? classTypeVariables[j] : methodTypeVariables[j - classTypeVariablesArity];
TypeVariableBinding substitutedVariable = (TypeVariableBinding) map.get(originalVariable.unannotated());
TypeVariableBinding substitutedVariable = map.get(originalVariable.unannotated());

TypeBinding substitutedSuperclass = Scope.substitute(substitution, originalVariable.superclass);
ReferenceBinding[] substitutedInterfaces = Scope.substitute(substitution, originalVariable.superInterfaces);
Expand Down
Loading

0 comments on commit c1bdc21

Please sign in to comment.