diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index b0214a631e8b..ac27b74c77b2 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -181,6 +181,11 @@ object Contexts { protected def searchHistory_= (searchHistory: SearchHistory) = _searchHistory = searchHistory def searchHistory: SearchHistory = _searchHistory + /** Those fields are used to cache phases created in withPhase. + * phasedCtx is first phase with altered phase ever requested. + * phasedCtxs is array that uses phaseId's as indexes, + * contexts are created only on request and cached in this array + */ private var phasedCtx: Context = _ private var phasedCtxs: Array[Context] = _ diff --git a/src/dotty/tools/dotc/core/Phases.scala b/src/dotty/tools/dotc/core/Phases.scala index 8b5606da245b..eb3b1d7fc061 100644 --- a/src/dotty/tools/dotc/core/Phases.scala +++ b/src/dotty/tools/dotc/core/Phases.scala @@ -67,6 +67,38 @@ object Phases { override def lastPhaseId(implicit ctx: Context) = id } + /** Squash TreeTransform's beloning to same sublist to a single TreeTransformer + * Each TreeTransform gets own period, + * whereas a combined TreeTransformer gets period equal to union of periods of it's TreeTransforms + * first TreeTransformer emitted is PostTyperTransformer that simplifies trees, see it's documentation + */ + private def squashPhases(phasess: List[List[Phase]]): Array[Phase] = { + val squashedPhases = ListBuffer[Phase]() + var postTyperEmmited = false + var i = 0 + while (i < phasess.length) { + if (phasess(i).length > 1) { + assert(phasess(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed") + + val transforms = phasess(i).asInstanceOf[List[TreeTransform]] + val block = + if (!postTyperEmmited) { + postTyperEmmited = true + new PostTyperTransformer { + override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") + override def transformations: Array[TreeTransform] = transforms.toArray + } + } else new TreeTransformer { + override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") + override def transformations: Array[TreeTransform] = transforms.toArray + } + squashedPhases += block + block.init(this, phasess(i).head.id, phasess(i).last.id) + } else squashedPhases += phasess(i).head + i += 1 + } + (NoPhase :: squashedPhases.toList ::: new TerminalPhase :: Nil).toArray + } /** Use the following phases in the order they are given. * The list should never contain NoPhase. @@ -94,31 +126,7 @@ object Phases { } if (squash) { - val squashedPhases = ListBuffer[Phase]() - var postTyperEmmited = false - var i = 0 - while (i < phasess.length) { - if (phasess(i).length > 1) { - assert(phasess(i).forall(x => x.isInstanceOf[TreeTransform]), "Only tree transforms can be squashed") - - val transforms = phasess(i).asInstanceOf[List[TreeTransform]] - val block = - if (!postTyperEmmited) { - postTyperEmmited = true - new PostTyperTransformer { - override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") - override def transformations: Array[TreeTransform] = transforms.toArray - } - } else new TreeTransformer { - override def name: String = transformations.map(_.name).mkString("TreeTransform:{", ", ", "}") - override def transformations: Array[TreeTransform] = transforms.toArray - } - squashedPhases += block - block.init(this, phasess(i).head.id, phasess(i).last.id) - } else squashedPhases += phasess(i).head - i += 1 - } - this.squashedPhases = (NoPhase::squashedPhases.toList :::new TerminalPhase :: Nil).toArray + this.squashedPhases = squashPhases(phasess) } else { this.squashedPhases = this.phases } diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala index 842e2f81f7f4..9fb580ae8b95 100644 --- a/src/dotty/tools/dotc/core/transform/Erasure.scala +++ b/src/dotty/tools/dotc/core/transform/Erasure.scala @@ -17,7 +17,7 @@ object Erasure { (if (isConstructor) 4 else 0) + (if (wildcardOK) 8 else 0) - private var erasures = new Array[Erasure](16) + private val erasures = new Array[Erasure](16) for { isJava <- List(false, true) diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala index 425410ae7ed6..0e182a99a8e5 100644 --- a/src/dotty/tools/dotc/transform/TreeTransform.scala +++ b/src/dotty/tools/dotc/transform/TreeTransform.scala @@ -23,8 +23,6 @@ object TreeTransforms { * * If all transforms in a group are NoTransforms, the tree is no longer traversed. * - * @param group The group this transform belongs to - * @param idx The index of this transform in its group * * Performance analysis: Taking the dotty compiler frontend as a use case, we are aiming for a warm performance of * about 4000 lines / sec. This means 6 seconds for a codebase of 24'000 lines. Of these the frontend consumes @@ -346,6 +344,11 @@ object TreeTransforms { nxTransStats = indexUpdate(prev.nxTransStats, changedTansformation, transformationIndex, "transformStats", copy) } + /** + * Those arrays are used as "execution plan" in order to only execute non-tivial transformations\preparations + * for every integer i array(i) contains first non trivial transformation\preparation on particular tree subtype. + * If no nontrivial transformation are left stored value is greater than transformers.size + */ var nxPrepIdent: Array[Int] = _ var nxPrepSelect: Array[Int] = _ var nxPrepThis: Array[Int] = _ diff --git a/src/dotty/tools/dotc/util/SimpleMap.scala b/src/dotty/tools/dotc/util/SimpleMap.scala index 84b9cb25814a..7bd263f0f35e 100644 --- a/src/dotty/tools/dotc/util/SimpleMap.scala +++ b/src/dotty/tools/dotc/util/SimpleMap.scala @@ -174,7 +174,7 @@ object SimpleMap { return { if (v eq bindings(i + 1)) this else { - val bindings1 = bindings.clone.asInstanceOf[Array[AnyRef]] + val bindings1 = bindings.clone bindings1(i + 1) = v new MapMore(bindings1) } @@ -204,7 +204,7 @@ object SimpleMap { val v = value(i) val v1 = f(key(i), v) if ((v1 ne v) && (bindings1 eq bindings)) - bindings1 = bindings.clone.asInstanceOf[Array[AnyRef]] + bindings1 = bindings.clone bindings1(i) = bindings(i) bindings1(i + 1) = v1 i += 2