aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/Periods.scala
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-11-02 11:08:28 +0100
committerGuillaume Martres <smarter@ubuntu.com>2016-11-22 01:35:07 +0100
commit8a61ff432543a29234193cd1f7c14abd3f3d31a0 (patch)
treea8147561d307af862c295cfc8100d271063bb0dd /compiler/src/dotty/tools/dotc/core/Periods.scala
parent6a455fe6da5ff9c741d91279a2dc6fe2fb1b472f (diff)
downloaddotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.gz
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.tar.bz2
dotty-8a61ff432543a29234193cd1f7c14abd3f3d31a0.zip
Move compiler and compiler tests to compiler dir
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Periods.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Periods.scala159
1 files changed, 159 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Periods.scala b/compiler/src/dotty/tools/dotc/core/Periods.scala
new file mode 100644
index 000000000..6efadab7f
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/core/Periods.scala
@@ -0,0 +1,159 @@
+package dotty.tools.dotc.core
+
+import Contexts._
+import dotty.tools.dotc.util.DotClass
+
+/** 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 extends DotClass { self: Context =>
+ import Periods._
+
+ /** The current phase identifier */
+ def phaseId: Int = period.phaseId
+
+ /** The current run identifier */
+ def runId: Int = period.runId
+
+ /** Execute `op` at given period */
+ def atPeriod[T](pd: Period)(op: Context => T): T =
+ op(ctx.fresh.setPeriod(pd))
+
+ /** Execute `op` at given phase id */
+ def atPhase[T](pid: PhaseId)(op: Context => T): T =
+ op(ctx.withPhase(pid))
+
+ /** The period containing the current period where denotations do not change.
+ * We compute this by taking as first phase the first phase less or equal to
+ * the current phase that has the same "nextTransformerId". As last phase
+ * we take the next transformer id following the current phase.
+ */
+ def stablePeriod = {
+ var first = phaseId
+ val nxTrans = ctx.base.nextDenotTransformerId(first)
+ while (first - 1 > NoPhaseId && (ctx.base.nextDenotTransformerId(first - 1) == nxTrans)) {
+ first -= 1
+ }
+ Period(runId, first, nxTrans)
+ }
+}
+
+object Periods {
+
+ /** A period is a contiguous sequence of phase ids in some run.
+ * It is coded as follows:
+ *
+ * sign, always 0 1 bit
+ * runid 19 bits
+ * last phase id: 6 bits
+ * #phases before last: 6 bits
+ *
+ * // Dmitry: sign == 0 isn't actually always true, in some cases phaseId == -1 is used for shifts, that easily creates code < 0
+ */
+ class Period(val code: Int) extends AnyVal {
+
+ /** The run identifier of this period. */
+ def runId: RunId = code >>> (PhaseWidth * 2)
+
+ /** The phase identifier of this single-phase period. */
+ def phaseId: PhaseId = (code >>> PhaseWidth) & PhaseMask
+
+ /** The last phase of this period */
+ def lastPhaseId: PhaseId =
+ (code >>> PhaseWidth) & PhaseMask
+
+ /** The first phase of this period */
+ def firstPhaseId = lastPhaseId - (code & PhaseMask)
+
+ def containsPhaseId(id: PhaseId) = firstPhaseId <= id && id <= lastPhaseId
+
+ /** Does this period contain given period? */
+ def contains(that: Period): Boolean = {
+ // Let this = (r1, l1, d1), that = (r2, l2, d2)
+ // where r = runid, l = last phase, d = duration - 1
+ // Then seen as intervals:
+ //
+ // this = r1 / (l1 - d1) .. l1
+ // that = r2 / (l2 - d2) .. l2
+ //
+ // Let's compute:
+ //
+ // lastDiff = X * 2^5 + (l1 - l2) mod 2^5
+ // where X >= 0, X == 0 iff r1 == r2 & l1 - l2 >= 0
+ // result = lastDiff + d2 <= d1
+ // We have:
+ // lastDiff + d2 <= d1
+ // iff X == 0 && l1 - l2 >= 0 && l1 - l2 + d2 <= d1
+ // iff r1 == r2 & l1 >= l2 && l1 - d1 <= l2 - d2
+ // q.e.d
+ val lastDiff = (code - that.code) >>> PhaseWidth
+ lastDiff + (that.code & PhaseMask ) <= (this.code & PhaseMask)
+ }
+
+ /** Does this period overlap with given period? */
+ def overlaps(that: Period): Boolean =
+ this.runId == that.runId &&
+ this.firstPhaseId <= that.lastPhaseId &&
+ that.firstPhaseId <= this.lastPhaseId
+
+ /** The intersection of two periods */
+ def & (that: Period): Period =
+ if (this overlaps that)
+ Period(
+ this.runId,
+ this.firstPhaseId max that.firstPhaseId,
+ this.lastPhaseId min that.lastPhaseId)
+ else
+ Nowhere
+
+ def | (that: Period): Period =
+ Period(this.runId,
+ this.firstPhaseId min that.firstPhaseId,
+ this.lastPhaseId max that.lastPhaseId)
+
+ override def toString = s"Period($firstPhaseId..$lastPhaseId, run = $runId)"
+ }
+
+ object Period {
+
+ /** The single-phase period consisting of given run id and phase id */
+ def apply(rid: RunId, pid: PhaseId): Period = {
+ new Period(((rid << PhaseWidth) | pid) << PhaseWidth)
+ }
+
+ /** The period consisting of given run id, and lo/hi phase ids */
+ def apply(rid: RunId, loPid: PhaseId, hiPid: PhaseId): Period = {
+ new Period(((rid << PhaseWidth) | hiPid) << PhaseWidth | (hiPid - loPid))
+ }
+
+ /** The interval consisting of all periods of given run id */
+ def allInRun(rid: RunId) = {
+ apply(rid, 0, PhaseMask)
+ }
+ }
+
+ final val Nowhere = new Period(0)
+
+ final val InitialPeriod = Period(InitialRunId, FirstPhaseId)
+
+ final val InvalidPeriod = Period(NoRunId, NoPhaseId)
+
+ /** An ordinal number for compiler runs. First run has number 1. */
+ type RunId = Int
+ final val NoRunId = 0
+ final val InitialRunId = 1
+ final val RunWidth = java.lang.Integer.SIZE - PhaseWidth * 2 - 1/* sign */
+ final val MaxPossibleRunId = (1 << RunWidth) - 1
+
+ /** 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 = 6
+ final val PhaseMask = (1 << PhaseWidth) - 1
+ final val MaxPossiblePhaseId = PhaseMask
+}