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
104
105
|
package dotty.tools.dotc.core
import Contexts._
/** Periods are the central "clock" of the compiler.
* A period consists of a run id and a phase id.
* run ids represent compiler runs
* phase ids represent compiler phases
*/
abstract class Periods { self: Context =>
import Periods._
/** The current phase identifier */
def phaseId = phaseIdOf(period)
/** The current run identifier */
def runId = runIdOf(period)
/** A new context that differs from the current one in its period */
def withPeriod(pd: Period): Context =
if (period == pd) this
else new SubContext(self) {
override val period = pd
}
/** Execute `op` at given period */
def atPeriod[T](pd: Period)(op: Context => T) =
op(ctx withPeriod pd)
/** Execute `op` at given phase id */
def atPhase[T](pid: PhaseId)(op: Context => T) =
op(ctx withPeriod periodOf(period, pid))
}
object Periods {
/** A period is an ordinal number for a phase in a run.
* Phases in later runs have higher periods than phases in earlier runs.
* Later phases have higher periods than earlier phases in the same run.
* Periods are coded (in big endian) as:
*
* sign, always 0 1 bit
* runid 21 bits
* phase id: 5 bits
* unused: 5 bits
*/
type Period = Int
final val NoPeriod = 0
/** A period interval is an interval between two periods that share the same runid.
* It is coded as follows:
*
* sign, always 0 1 bit
* runid 21 bits
* last phase id: 5 bits
* #phases before last: 5 bits
*/
type Interval = Int
final val Nowhere = NoPeriod
/** An ordinal number for compiler runs. First run has number 1. */
type RunId = Int
final val NoRunId = 0
/** An ordinal number for phases. First phase has number 1. */
type PhaseId = Int
final val NoPhaseId = 0
final val FirstPhaseId = 1
/** The number of bits needed to encode a phase identifier. */
final val PhaseWidth = 5
final val PhaseMask = (1 << PhaseWidth) - 1
/** The run identifier of the given period. */
final def runIdOf(period: Period): RunId = period >>> (PhaseWidth * 2)
/** The phase identifier of the given period. */
final def phaseIdOf(period: Period): PhaseId = (period >>> PhaseWidth) & PhaseMask
/** The last phase of the given interval */
final def lastPhaseIdOf(ivl: Interval) = phaseIdOf(ivl)
/** The first phase of the given interval */
final def firstPhaseIdOf(ivl: Interval) = lastPhaseIdOf(ivl) - (ivl & PhaseMask)
/** Does given interval contain given period */
final def containsPeriod(ivl: Interval, period: Period): Boolean =
((ivl - period) >>> PhaseWidth) <= (ivl & PhaseMask)
final def intervalsOverlap(ivl1: Interval, ivl2: Interval): Boolean = ???
final def intersection(ivl1: Interval, ivl2: Interval): Interval = ???
/** The period consisting of given run id and phase id */
final def periodOf(rid: RunId, pid: PhaseId): Period =
((rid << PhaseWidth) | pid) << PhaseWidth
/** The interval consisting of given run id, and lo/hi phase ids */
final def intervalOf(rid: RunId, loPid: PhaseId, hiPid: PhaseId): Interval =
periodOf(rid, hiPid) | (hiPid - loPid)
/** The interval consisting of all periods of given run id */
def allPeriods(rid: RunId): Interval = intervalOf(rid, 0, PhaseMask)
}
|