summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-02-18 14:02:08 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-02-18 14:16:56 +1000
commitb6cbee9d81320524aa2e8a3d80dbf2062dd43fd2 (patch)
treec20dab2c227285ff184a4a83e6d0e8ee37cf0983 /src/reflect
parentda49d9a00ec373a0e7f2ffe946a897a65c9b0741 (diff)
downloadscala-b6cbee9d81320524aa2e8a3d80dbf2062dd43fd2.tar.gz
scala-b6cbee9d81320524aa2e8a3d80dbf2062dd43fd2.tar.bz2
scala-b6cbee9d81320524aa2e8a3d80dbf2062dd43fd2.zip
SI-9157 Avoid exponential blowup with chained type projections
Calling `findMember` in the enclosed test was calling into `NonClassTypeRef#relativeInfo` an exponentially-increasing number of times, with respect to the length of the chained type projections. The numbers of calls increased as: 26, 326, 3336, 33446, 334556. Can any pattern spotters in the crowd that can identify the sequence? (I can't.) Tracing the calls saw we were computing the same `memberType` repeatedly. This part of the method was not guarded by the cache. I have changed the method to use the standard idiom of using the current period for cache invalidation. The enclosed test now compiles promptly, rather than in geological time.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala10
1 files changed, 5 insertions, 5 deletions
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index ce36f7efa3..8f114caac0 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -1976,13 +1976,13 @@ trait Types
* usage scenario.
*/
private var relativeInfoCache: Type = _
- private var memberInfoCache: Type = _
+ private var relativeInfoPeriod: Period = NoPeriod
- private[Types] def relativeInfo = {
- val memberInfo = pre.memberInfo(sym)
- if (relativeInfoCache == null || (memberInfo ne memberInfoCache)) {
- memberInfoCache = memberInfo
+ private[Types] def relativeInfo = /*trace(s"relativeInfo(${safeToString}})")*/{
+ if (relativeInfoPeriod != currentPeriod) {
+ val memberInfo = pre.memberInfo(sym)
relativeInfoCache = transformInfo(memberInfo)
+ relativeInfoPeriod = currentPeriod
}
relativeInfoCache
}