Skip to content

Commit 1dda6e1

Browse files
authored
Merge pull request #3223 from dotty-staging/try-optimize-3
Some further optimizations
2 parents 299bb09 + 93f0ff3 commit 1dda6e1

File tree

5 files changed

+170
-54
lines changed

5 files changed

+170
-54
lines changed

compiler/src/dotty/tools/dotc/core/Contexts.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ object Contexts {
606606
/** A table for hash consing unique types */
607607
private[core] val uniques = new util.HashSet[Type](Config.initialUniquesCapacity) {
608608
override def hash(x: Type): Int = x.hash
609+
override def isEqual(x: Type, y: Type) = x.eql(y)
609610
}
610611

611612
/** A table for hash consing unique applied types */

compiler/src/dotty/tools/dotc/core/Decorators.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ object Decorators {
119119
loop(xs, ys)
120120
}
121121

122+
@tailrec final def eqElements(ys: List[AnyRef]): Boolean = xs match {
123+
case x :: _ =>
124+
ys match {
125+
case y :: _ =>
126+
x.asInstanceOf[AnyRef].eq(y) &&
127+
xs.tail.eqElements(ys.tail)
128+
case _ => false
129+
}
130+
case nil => ys.isEmpty
131+
}
132+
122133
/** Union on lists seen as sets */
123134
def | (ys: List[T]): List[T] = xs ++ (ys filterNot (xs contains _))
124135

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

Lines changed: 139 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,11 @@ object Types {
13541354
* compute hash and use it as the type's hashCode.
13551355
*/
13561356
def hash: Int
1357+
1358+
/** Equality used for hash-consing; uses `eq` on all recursive invocations.
1359+
*/
1360+
def eql(that: Type): Boolean = this.equals(that)
1361+
13571362
} // end Type
13581363

13591364
// ----- Type categories ----------------------------------------------
@@ -1927,6 +1932,8 @@ object Types {
19271932

19281933
override def computeHash = unsupported("computeHash")
19291934

1935+
override def eql(that: Type) = this eq that // safe because named types are hash-consed separately
1936+
19301937
/* A version of toString which also prints aliases. Can be used for debugging
19311938
override def toString =
19321939
if (isTerm) s"TermRef($prefix, $name)"
@@ -2097,7 +2104,13 @@ object Types {
20972104
def cls(implicit ctx: Context): ClassSymbol = tref.stableInRunSymbol.asClass
20982105
override def underlying(implicit ctx: Context): Type =
20992106
if (ctx.erasedTypes) tref else cls.classInfo.selfType
2107+
21002108
override def computeHash = doHash(tref)
2109+
2110+
override def eql(that: Type) = that match {
2111+
case that: ThisType => tref.eq(that.tref)
2112+
case _ => false
2113+
}
21012114
}
21022115

21032116
final class CachedThisType(tref: TypeRef) extends ThisType(tref)
@@ -2119,7 +2132,13 @@ object Types {
21192132
def derivedSuperType(thistpe: Type, supertpe: Type)(implicit ctx: Context) =
21202133
if ((thistpe eq this.thistpe) && (supertpe eq this.supertpe)) this
21212134
else SuperType(thistpe, supertpe)
2135+
21222136
override def computeHash = doHash(thistpe, supertpe)
2137+
2138+
override def eql(that: Type) = that match {
2139+
case that: SuperType => thistpe.eq(that.thistpe) && supertpe.eq(that.supertpe)
2140+
case _ => false
2141+
}
21232142
}
21242143

21252144
final class CachedSuperType(thistpe: Type, supertpe: Type) extends SuperType(thistpe, supertpe)
@@ -2134,6 +2153,7 @@ object Types {
21342153
/** A constant type with single `value`. */
21352154
abstract case class ConstantType(value: Constant) extends CachedProxyType with SingletonType {
21362155
override def underlying(implicit ctx: Context) = value.tpe
2156+
21372157
override def computeHash = doHash(value)
21382158
}
21392159

@@ -2161,7 +2181,7 @@ object Types {
21612181
def evaluating = computed && myRef == null
21622182
override def underlying(implicit ctx: Context) = ref
21632183
override def toString = s"LazyRef(${if (computed) myRef else "..."})"
2164-
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
2184+
override def equals(other: Any) = this.eq(other.asInstanceOf[AnyRef])
21652185
override def hashCode = System.identityHashCode(this)
21662186
}
21672187

@@ -2199,6 +2219,14 @@ object Types {
21992219
else parent
22002220

22012221
override def computeHash = doHash(refinedName, refinedInfo, parent)
2222+
2223+
override def eql(that: Type) = that match {
2224+
case that: RefinedType =>
2225+
refinedName.eq(that.refinedName) &&
2226+
refinedInfo.eq(that.refinedInfo) &&
2227+
parent.eq(that.parent)
2228+
case _ => false
2229+
}
22022230
}
22032231

22042232
class CachedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)
@@ -2240,11 +2268,6 @@ object Types {
22402268
if (parent eq this.parent) this
22412269
else RecType.closeOver(rt => parent.substRecThis(this, rt.recThis))
22422270

2243-
override def equals(other: Any) = other match {
2244-
case other: RecType => other.parent == this.parent
2245-
case _ => false
2246-
}
2247-
22482271
def isReferredToBy(tp: Type)(implicit ctx: Context): Boolean = {
22492272
val refacc = new TypeAccumulator[Boolean] {
22502273
override def apply(x: Boolean, tp: Type) = x || {
@@ -2260,6 +2283,17 @@ object Types {
22602283
}
22612284

22622285
override def computeHash = doHash(parent)
2286+
2287+
override def equals(that: Any) = that match {
2288+
case that: RecType => parent == that.parent
2289+
case _ => false
2290+
}
2291+
2292+
override def eql(that: Type) = that match {
2293+
case that: RecType => parent.eq(that.parent)
2294+
case _ => false
2295+
}
2296+
22632297
override def toString = s"RecType($parent | $hashCode)"
22642298

22652299
private def checkInst(implicit ctx: Context): this.type = this // debug hook
@@ -2355,6 +2389,11 @@ object Types {
23552389
derivedAndType(tp1, tp2)
23562390

23572391
override def computeHash = doHash(tp1, tp2)
2392+
2393+
override def eql(that: Type) = that match {
2394+
case that: AndType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
2395+
case _ => false
2396+
}
23582397
}
23592398

23602399
final class CachedAndType(tp1: Type, tp2: Type) extends AndType(tp1, tp2)
@@ -2411,6 +2450,11 @@ object Types {
24112450
derivedOrType(tp1, tp2)
24122451

24132452
override def computeHash = doHash(tp1, tp2)
2453+
2454+
override def eql(that: Type) = that match {
2455+
case that: OrType => tp1.eq(that.tp1) && tp2.eq(that.tp2)
2456+
case _ => false
2457+
}
24142458
}
24152459

24162460
final class CachedOrType(tp1: Type, tp2: Type) extends OrType(tp1, tp2)
@@ -2465,10 +2509,18 @@ object Types {
24652509
extends CachedProxyType with TermType with MethodicType {
24662510
override def resultType(implicit ctx: Context): Type = resType
24672511
override def underlying(implicit ctx: Context): Type = resType
2512+
24682513
def computeSignature(implicit ctx: Context): Signature = resultSignature
2514+
24692515
def derivedExprType(resType: Type)(implicit ctx: Context) =
24702516
if (resType eq this.resType) this else ExprType(resType)
2517+
24712518
override def computeHash = doHash(resType)
2519+
2520+
override def eql(that: Type) = that match {
2521+
case that: ExprType => resType.eq(that.resType)
2522+
case _ => false
2523+
}
24722524
}
24732525

24742526
final class CachedExprType(resultType: Type) extends ExprType(resultType)
@@ -2555,10 +2607,20 @@ object Types {
25552607
// Defined here instead of in LambdaType for efficiency
25562608
final override def equals(that: Any) = that match {
25572609
case that: HKLambda =>
2558-
this.paramNames == that.paramNames &&
2559-
this.paramInfos == that.paramInfos &&
2560-
this.resType == that.resType &&
2561-
(this.companion eq that.companion)
2610+
paramNames == that.paramNames &&
2611+
paramInfos == that.paramInfos &&
2612+
resType == that.resType &&
2613+
companion.eq(that.companion)
2614+
case _ =>
2615+
false
2616+
}
2617+
2618+
final override def eql(that: Type) = that match {
2619+
case that: HKLambda =>
2620+
paramNames.equals(that.paramNames) &&
2621+
paramInfos.equals(that.paramInfos) &&
2622+
resType.equals(that.resType) &&
2623+
companion.eq(that.companion)
25622624
case _ =>
25632625
false
25642626
}
@@ -2570,10 +2632,20 @@ object Types {
25702632
// Defined here instead of in LambdaType for efficiency
25712633
final override def equals(that: Any) = that match {
25722634
case that: MethodOrPoly =>
2573-
this.paramNames == that.paramNames &&
2574-
this.paramInfos == that.paramInfos &&
2575-
this.resType == that.resType &&
2576-
(this.companion eq that.companion)
2635+
paramNames == that.paramNames &&
2636+
paramInfos == that.paramInfos &&
2637+
resType == that.resType &&
2638+
companion.eq(that.companion)
2639+
case _ =>
2640+
false
2641+
}
2642+
2643+
final override def eql(that: Type) = that match {
2644+
case that: MethodOrPoly =>
2645+
paramNames.eqElements(that.paramNames) &&
2646+
paramInfos.eqElements(that.paramInfos) &&
2647+
resType.eq(that.resType) &&
2648+
companion.eq(that.companion)
25772649
case _ =>
25782650
false
25792651
}
@@ -3046,6 +3118,7 @@ object Types {
30463118
final class CachedAppliedType(tycon: Type, args: List[Type], hc: Int) extends AppliedType(tycon, args) {
30473119
myHash = hc
30483120
override def computeHash = unsupported("computeHash")
3121+
override def eql(that: Type) = this eq that // safe because applied types are hash-consed separately
30493122
}
30503123

30513124
object AppliedType {
@@ -3093,6 +3166,11 @@ object Types {
30933166
def derivedTypeArgRef(prefix: Type)(implicit ctx: Context): Type =
30943167
if (prefix eq this.prefix) this else TypeArgRef(prefix, clsRef, idx)
30953168
override def computeHash = doHash(idx, prefix, clsRef)
3169+
3170+
override def eql(that: Type) = that match {
3171+
case that: TypeArgRef => prefix.eq(that.prefix) && clsRef.eq(that.clsRef) && idx == that.idx
3172+
case _ => false
3173+
}
30963174
}
30973175

30983176
final class CachedTypeArgRef(prefix: Type, clsRef: TypeRef, idx: Int) extends TypeArgRef(prefix, clsRef, idx)
@@ -3134,11 +3212,10 @@ object Types {
31343212
}
31353213

31363214
override def computeHash = doHash(paramNum, binder.identityHash)
3215+
31373216
override def equals(that: Any) = that match {
3138-
case that: ParamRef =>
3139-
(this.binder eq that.binder) && this.paramNum == that.paramNum
3140-
case _ =>
3141-
false
3217+
case that: ParamRef => binder.eq(that.binder) && paramNum == that.paramNum
3218+
case _ => false
31423219
}
31433220

31443221
override def toString =
@@ -3188,10 +3265,12 @@ object Types {
31883265
// need to customize hashCode and equals to prevent infinite recursion
31893266
// between RecTypes and RecRefs.
31903267
override def computeHash = addDelta(binder.identityHash, 41)
3268+
31913269
override def equals(that: Any) = that match {
3192-
case that: RecThis => this.binder eq that.binder
3270+
case that: RecThis => binder.eq(that.binder)
31933271
case _ => false
31943272
}
3273+
31953274
override def toString =
31963275
try s"RecThis(${binder.hashCode})"
31973276
catch {
@@ -3207,7 +3286,7 @@ object Types {
32073286
def derivedSkolemType(info: Type)(implicit ctx: Context) =
32083287
if (info eq this.info) this else SkolemType(info)
32093288
override def hashCode: Int = identityHash
3210-
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
3289+
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
32113290

32123291
def withName(name: Name): this.type = { myRepr = name; this }
32133292

@@ -3309,7 +3388,7 @@ object Types {
33093388
}
33103389

33113390
override def computeHash: Int = identityHash
3312-
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
3391+
override def equals(that: Any) = this.eq(that.asInstanceOf[AnyRef])
33133392

33143393
override def toString = {
33153394
def instStr = if (inst.exists) s" -> $inst" else ""
@@ -3389,6 +3468,16 @@ object Types {
33893468

33903469
override def computeHash = doHash(cls, prefix)
33913470

3471+
override def eql(that: Type) = that match {
3472+
case that: ClassInfo =>
3473+
prefix.eq(that.prefix) &&
3474+
cls.eq(that.cls) &&
3475+
classParents.eqElements(that.classParents) &&
3476+
decls.eq(that.decls) &&
3477+
selfInfo.eq(that.selfInfo)
3478+
case _ => false
3479+
}
3480+
33923481
override def toString = s"ClassInfo($prefix, $cls, $classParents)"
33933482
}
33943483

@@ -3459,15 +3548,16 @@ object Types {
34593548

34603549
override def computeHash = doHash(lo, hi)
34613550

3462-
// @!!! we are not systematic when we do referntial vs structural comparisons.
3463-
// Do referential everywhere?
34643551
override def equals(that: Any): Boolean = that match {
3465-
case that: TypeAlias =>
3466-
false
3467-
case that: TypeBounds =>
3468-
(this.lo eq that.lo) && (this.hi eq that.hi)
3469-
case _ =>
3470-
false
3552+
case that: TypeAlias => false
3553+
case that: TypeBounds => lo == that.lo && hi == that.hi
3554+
case _ => false
3555+
}
3556+
3557+
override def eql(that: Type) = that match {
3558+
case that: TypeAlias => false
3559+
case that: TypeBounds => lo.eq(that.lo) && hi.eq(that.hi)
3560+
case _ => false
34713561
}
34723562
}
34733563

@@ -3482,10 +3572,13 @@ object Types {
34823572
override def computeHash = doHash(alias)
34833573

34843574
override def equals(that: Any): Boolean = that match {
3485-
case that: TypeAlias =>
3486-
this.alias eq that.alias
3487-
case _ =>
3488-
false
3575+
case that: TypeAlias => alias == that.alias
3576+
case _ => false
3577+
}
3578+
3579+
override def eql(that: Type): Boolean = that match {
3580+
case that: TypeAlias => alias.eq(that.alias)
3581+
case _ => false
34893582
}
34903583
}
34913584

@@ -3530,9 +3623,15 @@ object Types {
35303623

35313624
/** The type of an erased array */
35323625
abstract case class JavaArrayType(elemType: Type) extends CachedGroundType with ValueType {
3533-
override def computeHash = doHash(elemType)
35343626
def derivedJavaArrayType(elemtp: Type)(implicit ctx: Context) =
35353627
if (elemtp eq this.elemType) this else JavaArrayType(elemtp)
3628+
3629+
override def computeHash = doHash(elemType)
3630+
3631+
override def eql(that: Type) = that match {
3632+
case that: JavaArrayType => elemType.eq(that.elemType)
3633+
case _ => false
3634+
}
35363635
}
35373636
final class CachedJavaArrayType(elemType: Type) extends JavaArrayType(elemType)
35383637
object JavaArrayType {
@@ -3586,7 +3685,13 @@ object Types {
35863685
if (optBounds eq this.optBounds) this
35873686
else if (!optBounds.exists) WildcardType
35883687
else WildcardType(optBounds.asInstanceOf[TypeBounds])
3688+
35893689
override def computeHash = doHash(optBounds)
3690+
3691+
override def eql(that: Type) = that match {
3692+
case that: WildcardType => optBounds.eq(that.optBounds)
3693+
case _ => false
3694+
}
35903695
}
35913696

35923697
final class CachedWildcardType(optBounds: Type) extends WildcardType(optBounds)

0 commit comments

Comments
 (0)