blob: 10d7500f09220d91e2f46e92e85086fe42e40efb (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/* NSC -- new scala compiler
* Copyright 2005-2011 LAMP/EPFL
* @author Paul Phillips
*/
package scala.tools.nsc
package symtab
import scala.collection.{ mutable, immutable }
/** A cache for some entity whose validity depends on a monotonically
* increasing sequence number.
*/
abstract class SequencedCache[T >: Null] {
def zero: Int
def sequenceId: Int
def calculate(): T
/** If sequence numbers differ, this condition is consulted before
* updating the cached value.
*/
def isCacheValid: Boolean
/** Public so accesses can be inlined. */
@inline var cachedId: Int = 0
@inline var cachedValue: T = _
/** Puts cache back in uninitialized state. */
@inline final def clear() = {
cachedId = zero
cachedValue = null
}
/** Resets the sequence id without touching the cached value. */
@inline final def reset() = {
cachedId = zero
}
final def get(): T = {
if (cachedValue == null) {
cachedValue = calculate()
cachedId = sequenceId
}
else if (cachedId != sequenceId) {
if (!isCacheValid)
cachedValue = calculate()
cachedId = sequenceId
}
cachedValue
}
}
trait Caches {
self: SymbolTable =>
final def isValid(period: Period): Boolean =
period != 0 && runId(period) == currentRunId && {
val pid = phaseId(period)
if (phase.id > pid) infoTransformers.nextFrom(pid).pid >= phase.id
else infoTransformers.nextFrom(phase.id).pid >= pid
}
final def isValidForBaseClasses(period: Period): Boolean = {
def noChangeInBaseClasses(it: InfoTransformer, limit: Phase#Id): Boolean = (
it.pid >= limit ||
!it.changesBaseClasses && noChangeInBaseClasses(it.next, limit)
);
period != 0 && runId(period) == currentRunId && {
val pid = phaseId(period)
if (phase.id > pid) noChangeInBaseClasses(infoTransformers.nextFrom(pid), phase.id)
else noChangeInBaseClasses(infoTransformers.nextFrom(phase.id), pid)
}
}
abstract class PeriodCache[T >: Null] extends SequencedCache[T] {
final val zero = NoPeriod
@inline final def sequenceId = currentPeriod
}
abstract class ListOfTypesCache extends PeriodCache[List[Type]] {
@inline final def isCacheValid = isValidForBaseClasses(cachedId)
}
abstract class ListOfSymbolsCache extends PeriodCache[List[Symbol]] {
@inline final def isCacheValid = isValidForBaseClasses(cachedId)
}
abstract class BaseTypeSeqCache extends PeriodCache[BaseTypeSeq] {
@inline final def isCacheValid = isValidForBaseClasses(cachedId)
}
abstract class TypeCache extends PeriodCache[Type] {
@inline final def isCacheValid = isValid(cachedId)
}
abstract class TypeCacheForRunId extends SequencedCache[Type] {
final val zero = NoRunId
@inline final def sequenceId = currentRunId
@inline final override def isCacheValid = false
}
object TypeCache {
def apply(body: => Type): TypeCache = new TypeCache {
@inline final def calculate() = body
}
}
}
|