Skip to content

Commit a4597c4

Browse files
committed
Fix incorrect hashing leading to cache pollution
Before this commit, Hashable#addDelta did not work correctly when the input hash was the special value NotCached, instead of returning NotCached, it returned NotCached + delta. This means that many different values ended up being cached with the same hash when they should not be cached at all, this is especially bad since our HashSet implementation uses open addressing. I noticed this bug while working on a phase to collect API information for sbt (this phase needs to collect every member of a class, including inherited members), after enabling it, the compileStdLib test took ~500 seconds to complete, this commit reduces this to ~100 seconds.
1 parent 305a9f0 commit a4597c4

File tree

2 files changed

+4
-2
lines changed

2 files changed

+4
-2
lines changed

src/dotty/tools/dotc/core/Hashable.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ trait Hashable {
9292
protected final def doHash(x1: Int, x2: Int): Int =
9393
finishHash(hashing.mix(hashing.mix(hashSeed, x1), x2), 1)
9494

95-
protected final def addDelta(hc: Int, delta: Int) = avoidNotCached(hc + delta)
95+
protected final def addDelta(elemHash: Int, delta: Int) =
96+
if (elemHash == NotCached) NotCached
97+
else avoidNotCached(elemHash + delta)
9698

9799
private def avoidNotCached(h: Int) = if (h == NotCached) NotCachedAlt else h
98100
}

src/dotty/tools/dotc/core/Types.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2479,7 +2479,7 @@ object Types {
24792479
def copyBoundType(bt: BT) = new MethodParamImpl(bt, paramNum)
24802480

24812481
// need to customize hashCode and equals to prevent infinite recursion for dep meth types.
2482-
override def computeHash = addDelta(System.identityHashCode(binder), paramNum)
2482+
override def computeHash = addDelta(binder.identityHash, paramNum)
24832483
override def equals(that: Any) = that match {
24842484
case that: MethodParam =>
24852485
(this.binder eq that.binder) && this.paramNum == that.paramNum

0 commit comments

Comments
 (0)